blob: 6e11c409e10428ffc3cfa110fa1b2f7f46a3a790 [file] [log] [blame]
Erik Klineade3a8c2016-10-19 17:42:01 +09001/*
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
17package android.net.util;
18
Erik Kline84714bf2017-05-19 09:29:48 +090019import static android.net.util.PacketReader.DEFAULT_RECV_BUF_SIZE;
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +090020import static android.system.OsConstants.AF_INET6;
21import static android.system.OsConstants.IPPROTO_UDP;
22import static android.system.OsConstants.SOCK_DGRAM;
23import static android.system.OsConstants.SOCK_NONBLOCK;
24import static android.system.OsConstants.SOL_SOCKET;
25import static android.system.OsConstants.SO_SNDTIMEO;
26
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090027import static org.junit.Assert.assertEquals;
28import static org.junit.Assert.assertFalse;
29import static org.junit.Assert.assertTrue;
30import static org.junit.Assert.fail;
Erik Klineade3a8c2016-10-19 17:42:01 +090031
Erik Klinef840e072017-07-10 20:17:30 +090032import android.os.Handler;
33import android.os.HandlerThread;
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090034import android.support.test.filters.SmallTest;
35import android.support.test.runner.AndroidJUnit4;
Erik Klineade3a8c2016-10-19 17:42:01 +090036import android.system.ErrnoException;
37import android.system.Os;
38import android.system.StructTimeval;
39
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +090040import org.junit.After;
41import org.junit.Before;
42import org.junit.Test;
43import org.junit.runner.RunWith;
44
Erik Klineade3a8c2016-10-19 17:42:01 +090045import java.io.FileDescriptor;
Erik Klineade3a8c2016-10-19 17:42:01 +090046import java.net.DatagramPacket;
47import java.net.DatagramSocket;
48import java.net.Inet6Address;
49import java.net.InetAddress;
50import java.net.InetSocketAddress;
51import java.net.SocketException;
52import java.util.Arrays;
53import java.util.concurrent.CountDownLatch;
54import java.util.concurrent.TimeUnit;
55
Erik Klineade3a8c2016-10-19 17:42:01 +090056/**
Erik Kline84714bf2017-05-19 09:29:48 +090057 * Tests for PacketReader.
Erik Klineade3a8c2016-10-19 17:42:01 +090058 *
59 * @hide
60 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090061@RunWith(AndroidJUnit4.class)
62@SmallTest
Erik Kline84714bf2017-05-19 09:29:48 +090063public class PacketReaderTest {
Erik Klineade3a8c2016-10-19 17:42:01 +090064 static final InetAddress LOOPBACK6 = Inet6Address.getLoopbackAddress();
65 static final StructTimeval TIMEO = StructTimeval.fromMillis(500);
66
67 protected CountDownLatch mLatch;
68 protected FileDescriptor mLocalSocket;
69 protected InetSocketAddress mLocalSockName;
70 protected byte[] mLastRecvBuf;
Erik Klinef840e072017-07-10 20:17:30 +090071 protected boolean mStopped;
72 protected HandlerThread mHandlerThread;
Erik Kline84714bf2017-05-19 09:29:48 +090073 protected PacketReader mReceiver;
Erik Klineade3a8c2016-10-19 17:42:01 +090074
Erik Kline84714bf2017-05-19 09:29:48 +090075 class UdpLoopbackReader extends PacketReader {
Erik Klinef840e072017-07-10 20:17:30 +090076 public UdpLoopbackReader(Handler h) {
77 super(h);
78 }
79
80 @Override
81 protected FileDescriptor createFd() {
82 FileDescriptor s = null;
83 try {
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +090084 s = Os.socket(AF_INET6, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
Erik Klinef840e072017-07-10 20:17:30 +090085 Os.bind(s, LOOPBACK6, 0);
86 mLocalSockName = (InetSocketAddress) Os.getsockname(s);
87 Os.setsockoptTimeval(s, SOL_SOCKET, SO_SNDTIMEO, TIMEO);
88 } catch (ErrnoException|SocketException e) {
89 closeFd(s);
90 fail();
91 return null;
92 }
93
94 mLocalSocket = s;
95 return s;
96 }
97
98 @Override
99 protected void handlePacket(byte[] recvbuf, int length) {
100 mLastRecvBuf = Arrays.copyOf(recvbuf, length);
101 mLatch.countDown();
102 }
103
104 @Override
105 protected void onStart() {
106 mStopped = false;
107 mLatch.countDown();
108 }
109
110 @Override
111 protected void onStop() {
112 mStopped = true;
113 mLatch.countDown();
114 }
115 };
116
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900117 @Before
Erik Klineade3a8c2016-10-19 17:42:01 +0900118 public void setUp() {
119 resetLatch();
120 mLocalSocket = null;
121 mLocalSockName = null;
122 mLastRecvBuf = null;
Erik Klinef840e072017-07-10 20:17:30 +0900123 mStopped = false;
Erik Klineade3a8c2016-10-19 17:42:01 +0900124
Erik Kline84714bf2017-05-19 09:29:48 +0900125 mHandlerThread = new HandlerThread(PacketReaderTest.class.getSimpleName());
Erik Klinef840e072017-07-10 20:17:30 +0900126 mHandlerThread.start();
Erik Klineade3a8c2016-10-19 17:42:01 +0900127 }
128
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900129 @After
Erik Klinef840e072017-07-10 20:17:30 +0900130 public void tearDown() throws Exception {
131 if (mReceiver != null) {
132 mHandlerThread.getThreadHandler().post(() -> { mReceiver.stop(); });
133 waitForActivity();
134 }
Erik Klineade3a8c2016-10-19 17:42:01 +0900135 mReceiver = null;
Erik Klinef840e072017-07-10 20:17:30 +0900136 mHandlerThread.quit();
137 mHandlerThread = null;
Erik Klineade3a8c2016-10-19 17:42:01 +0900138 }
139
140 void resetLatch() { mLatch = new CountDownLatch(1); }
141
142 void waitForActivity() throws Exception {
Erik Klinef840e072017-07-10 20:17:30 +0900143 try {
144 mLatch.await(1000, TimeUnit.MILLISECONDS);
145 } finally {
146 resetLatch();
147 }
Erik Klineade3a8c2016-10-19 17:42:01 +0900148 }
149
150 void sendPacket(byte[] contents) throws Exception {
151 final DatagramSocket sender = new DatagramSocket();
152 sender.connect(mLocalSockName);
153 sender.send(new DatagramPacket(contents, contents.length));
154 sender.close();
155 }
156
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900157 @Test
Erik Klineade3a8c2016-10-19 17:42:01 +0900158 public void testBasicWorking() throws Exception {
Erik Klinef840e072017-07-10 20:17:30 +0900159 final Handler h = mHandlerThread.getThreadHandler();
160 mReceiver = new UdpLoopbackReader(h);
161
162 h.post(() -> { mReceiver.start(); });
163 waitForActivity();
Erik Klineade3a8c2016-10-19 17:42:01 +0900164 assertTrue(mLocalSockName != null);
165 assertEquals(LOOPBACK6, mLocalSockName.getAddress());
166 assertTrue(0 < mLocalSockName.getPort());
167 assertTrue(mLocalSocket != null);
Erik Klinef840e072017-07-10 20:17:30 +0900168 assertFalse(mStopped);
Erik Klineade3a8c2016-10-19 17:42:01 +0900169
170 final byte[] one = "one 1".getBytes("UTF-8");
171 sendPacket(one);
172 waitForActivity();
173 assertEquals(1, mReceiver.numPacketsReceived());
174 assertTrue(Arrays.equals(one, mLastRecvBuf));
Erik Klinef840e072017-07-10 20:17:30 +0900175 assertFalse(mStopped);
Erik Klineade3a8c2016-10-19 17:42:01 +0900176
177 final byte[] two = "two 2".getBytes("UTF-8");
178 sendPacket(two);
179 waitForActivity();
180 assertEquals(2, mReceiver.numPacketsReceived());
181 assertTrue(Arrays.equals(two, mLastRecvBuf));
Erik Klinef840e072017-07-10 20:17:30 +0900182 assertFalse(mStopped);
Erik Klineade3a8c2016-10-19 17:42:01 +0900183
184 mReceiver.stop();
185 waitForActivity();
186 assertEquals(2, mReceiver.numPacketsReceived());
187 assertTrue(Arrays.equals(two, mLastRecvBuf));
Erik Klinef840e072017-07-10 20:17:30 +0900188 assertTrue(mStopped);
189 mReceiver = null;
190 }
191
Erik Kline84714bf2017-05-19 09:29:48 +0900192 class NullPacketReader extends PacketReader {
193 public NullPacketReader(Handler h, int recvbufsize) {
Erik Klinef840e072017-07-10 20:17:30 +0900194 super(h, recvbufsize);
195 }
196
197 @Override
198 public FileDescriptor createFd() { return null; }
199 }
200
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900201 @Test
Erik Klinef840e072017-07-10 20:17:30 +0900202 public void testMinimalRecvBufSize() throws Exception {
203 final Handler h = mHandlerThread.getThreadHandler();
204
205 for (int i : new int[]{-1, 0, 1, DEFAULT_RECV_BUF_SIZE-1}) {
Erik Kline84714bf2017-05-19 09:29:48 +0900206 final PacketReader b = new NullPacketReader(h, i);
Erik Klinef840e072017-07-10 20:17:30 +0900207 assertEquals(DEFAULT_RECV_BUF_SIZE, b.recvBufSize());
208 }
Erik Klineade3a8c2016-10-19 17:42:01 +0900209 }
210}