blob: 289dcade99a6470890acd0d629aa76d551c3cf16 [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;
Erik Klineade3a8c2016-10-19 17:42:01 +090034import android.system.ErrnoException;
35import android.system.Os;
36import android.system.StructTimeval;
37
Brett Chabot84151d92019-02-27 15:37:59 -080038import androidx.test.filters.SmallTest;
39import androidx.test.runner.AndroidJUnit4;
40
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +090041import org.junit.After;
42import org.junit.Before;
43import org.junit.Test;
44import org.junit.runner.RunWith;
45
Erik Klineade3a8c2016-10-19 17:42:01 +090046import java.io.FileDescriptor;
Erik Klineade3a8c2016-10-19 17:42:01 +090047import java.net.DatagramPacket;
48import java.net.DatagramSocket;
49import java.net.Inet6Address;
50import java.net.InetAddress;
51import java.net.InetSocketAddress;
52import java.net.SocketException;
53import java.util.Arrays;
54import java.util.concurrent.CountDownLatch;
55import java.util.concurrent.TimeUnit;
56
Erik Klineade3a8c2016-10-19 17:42:01 +090057/**
Erik Kline84714bf2017-05-19 09:29:48 +090058 * Tests for PacketReader.
Erik Klineade3a8c2016-10-19 17:42:01 +090059 *
60 * @hide
61 */
Hugo Benichi4a0c5d72017-10-11 11:26:25 +090062@RunWith(AndroidJUnit4.class)
63@SmallTest
Erik Kline84714bf2017-05-19 09:29:48 +090064public class PacketReaderTest {
Erik Klineade3a8c2016-10-19 17:42:01 +090065 static final InetAddress LOOPBACK6 = Inet6Address.getLoopbackAddress();
66 static final StructTimeval TIMEO = StructTimeval.fromMillis(500);
67
68 protected CountDownLatch mLatch;
69 protected FileDescriptor mLocalSocket;
70 protected InetSocketAddress mLocalSockName;
71 protected byte[] mLastRecvBuf;
Erik Klinef840e072017-07-10 20:17:30 +090072 protected boolean mStopped;
73 protected HandlerThread mHandlerThread;
Erik Kline84714bf2017-05-19 09:29:48 +090074 protected PacketReader mReceiver;
Erik Klineade3a8c2016-10-19 17:42:01 +090075
Erik Kline84714bf2017-05-19 09:29:48 +090076 class UdpLoopbackReader extends PacketReader {
Erik Klinef840e072017-07-10 20:17:30 +090077 public UdpLoopbackReader(Handler h) {
78 super(h);
79 }
80
81 @Override
82 protected FileDescriptor createFd() {
83 FileDescriptor s = null;
84 try {
Remi NGUYEN VAN231b52b2019-01-29 15:38:52 +090085 s = Os.socket(AF_INET6, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
Erik Klinef840e072017-07-10 20:17:30 +090086 Os.bind(s, LOOPBACK6, 0);
87 mLocalSockName = (InetSocketAddress) Os.getsockname(s);
88 Os.setsockoptTimeval(s, SOL_SOCKET, SO_SNDTIMEO, TIMEO);
89 } catch (ErrnoException|SocketException e) {
90 closeFd(s);
91 fail();
92 return null;
93 }
94
95 mLocalSocket = s;
96 return s;
97 }
98
99 @Override
100 protected void handlePacket(byte[] recvbuf, int length) {
101 mLastRecvBuf = Arrays.copyOf(recvbuf, length);
102 mLatch.countDown();
103 }
104
105 @Override
106 protected void onStart() {
107 mStopped = false;
108 mLatch.countDown();
109 }
110
111 @Override
112 protected void onStop() {
113 mStopped = true;
114 mLatch.countDown();
115 }
116 };
117
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900118 @Before
Erik Klineade3a8c2016-10-19 17:42:01 +0900119 public void setUp() {
120 resetLatch();
121 mLocalSocket = null;
122 mLocalSockName = null;
123 mLastRecvBuf = null;
Erik Klinef840e072017-07-10 20:17:30 +0900124 mStopped = false;
Erik Klineade3a8c2016-10-19 17:42:01 +0900125
Erik Kline84714bf2017-05-19 09:29:48 +0900126 mHandlerThread = new HandlerThread(PacketReaderTest.class.getSimpleName());
Erik Klinef840e072017-07-10 20:17:30 +0900127 mHandlerThread.start();
Erik Klineade3a8c2016-10-19 17:42:01 +0900128 }
129
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900130 @After
Erik Klinef840e072017-07-10 20:17:30 +0900131 public void tearDown() throws Exception {
132 if (mReceiver != null) {
133 mHandlerThread.getThreadHandler().post(() -> { mReceiver.stop(); });
134 waitForActivity();
135 }
Erik Klineade3a8c2016-10-19 17:42:01 +0900136 mReceiver = null;
Erik Klinef840e072017-07-10 20:17:30 +0900137 mHandlerThread.quit();
138 mHandlerThread = null;
Erik Klineade3a8c2016-10-19 17:42:01 +0900139 }
140
141 void resetLatch() { mLatch = new CountDownLatch(1); }
142
143 void waitForActivity() throws Exception {
Erik Klinef840e072017-07-10 20:17:30 +0900144 try {
145 mLatch.await(1000, TimeUnit.MILLISECONDS);
146 } finally {
147 resetLatch();
148 }
Erik Klineade3a8c2016-10-19 17:42:01 +0900149 }
150
151 void sendPacket(byte[] contents) throws Exception {
152 final DatagramSocket sender = new DatagramSocket();
153 sender.connect(mLocalSockName);
154 sender.send(new DatagramPacket(contents, contents.length));
155 sender.close();
156 }
157
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900158 @Test
Erik Klineade3a8c2016-10-19 17:42:01 +0900159 public void testBasicWorking() throws Exception {
Erik Klinef840e072017-07-10 20:17:30 +0900160 final Handler h = mHandlerThread.getThreadHandler();
161 mReceiver = new UdpLoopbackReader(h);
162
163 h.post(() -> { mReceiver.start(); });
164 waitForActivity();
Erik Klineade3a8c2016-10-19 17:42:01 +0900165 assertTrue(mLocalSockName != null);
166 assertEquals(LOOPBACK6, mLocalSockName.getAddress());
167 assertTrue(0 < mLocalSockName.getPort());
168 assertTrue(mLocalSocket != null);
Erik Klinef840e072017-07-10 20:17:30 +0900169 assertFalse(mStopped);
Erik Klineade3a8c2016-10-19 17:42:01 +0900170
171 final byte[] one = "one 1".getBytes("UTF-8");
172 sendPacket(one);
173 waitForActivity();
174 assertEquals(1, mReceiver.numPacketsReceived());
175 assertTrue(Arrays.equals(one, mLastRecvBuf));
Erik Klinef840e072017-07-10 20:17:30 +0900176 assertFalse(mStopped);
Erik Klineade3a8c2016-10-19 17:42:01 +0900177
178 final byte[] two = "two 2".getBytes("UTF-8");
179 sendPacket(two);
180 waitForActivity();
181 assertEquals(2, mReceiver.numPacketsReceived());
182 assertTrue(Arrays.equals(two, mLastRecvBuf));
Erik Klinef840e072017-07-10 20:17:30 +0900183 assertFalse(mStopped);
Erik Klineade3a8c2016-10-19 17:42:01 +0900184
185 mReceiver.stop();
186 waitForActivity();
187 assertEquals(2, mReceiver.numPacketsReceived());
188 assertTrue(Arrays.equals(two, mLastRecvBuf));
Erik Klinef840e072017-07-10 20:17:30 +0900189 assertTrue(mStopped);
190 mReceiver = null;
191 }
192
Erik Kline84714bf2017-05-19 09:29:48 +0900193 class NullPacketReader extends PacketReader {
194 public NullPacketReader(Handler h, int recvbufsize) {
Erik Klinef840e072017-07-10 20:17:30 +0900195 super(h, recvbufsize);
196 }
197
198 @Override
199 public FileDescriptor createFd() { return null; }
200 }
201
Hugo Benichi4a0c5d72017-10-11 11:26:25 +0900202 @Test
Erik Klinef840e072017-07-10 20:17:30 +0900203 public void testMinimalRecvBufSize() throws Exception {
204 final Handler h = mHandlerThread.getThreadHandler();
205
206 for (int i : new int[]{-1, 0, 1, DEFAULT_RECV_BUF_SIZE-1}) {
Erik Kline84714bf2017-05-19 09:29:48 +0900207 final PacketReader b = new NullPacketReader(h, i);
Erik Klinef840e072017-07-10 20:17:30 +0900208 assertEquals(DEFAULT_RECV_BUF_SIZE, b.recvBufSize());
209 }
Erik Klineade3a8c2016-10-19 17:42:01 +0900210 }
211}