blob: 57c258f8f28947fa5c6b975c58b5c0ba05c7cf22 [file] [log] [blame]
Christopher Wiley08725a82016-05-18 16:32:44 -07001/*
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 com.android.server.connectivity.tethering;
18
Erik Klineab6439b2017-06-06 19:24:21 +090019import static org.mockito.Matchers.any;
Christopher Wileyf972edc2016-05-23 16:17:30 -070020import static org.mockito.Matchers.anyString;
Erik Klineab6439b2017-06-06 19:24:21 +090021import static org.mockito.Matchers.eq;
Christopher Wileyf972edc2016-05-23 16:17:30 -070022import static org.mockito.Mockito.doThrow;
Christopher Wiley279eca32016-05-20 13:23:10 -070023import static org.mockito.Mockito.inOrder;
24import static org.mockito.Mockito.reset;
25import static org.mockito.Mockito.verify;
Christopher Wiley08725a82016-05-18 16:32:44 -070026import static org.mockito.Mockito.verifyNoMoreInteractions;
Christopher Wiley279eca32016-05-20 13:23:10 -070027import static org.mockito.Mockito.when;
Christopher Wiley08725a82016-05-18 16:32:44 -070028
Christopher Wileye90e0a72016-05-31 10:44:35 -070029import static android.net.ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
30import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
31import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
32import static android.net.ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
Erik Klinea954be92017-02-13 17:12:02 +090033import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
34import static android.net.ConnectivityManager.TETHERING_USB;
35import static android.net.ConnectivityManager.TETHERING_WIFI;
Christopher Wileye90e0a72016-05-31 10:44:35 -070036import static com.android.server.connectivity.tethering.IControlsTethering.STATE_AVAILABLE;
37import static com.android.server.connectivity.tethering.IControlsTethering.STATE_TETHERED;
38import static com.android.server.connectivity.tethering.IControlsTethering.STATE_UNAVAILABLE;
39
Christopher Wileycd0cfbb2016-05-31 14:43:08 -070040import android.net.ConnectivityManager;
Christopher Wiley08725a82016-05-18 16:32:44 -070041import android.net.INetworkStatsService;
Christopher Wiley279eca32016-05-20 13:23:10 -070042import android.net.InterfaceConfiguration;
Erik Klineab6439b2017-06-06 19:24:21 +090043import android.net.LinkProperties;
Erik Kline7747fd42017-05-12 16:52:48 +090044import android.net.util.SharedLog;
Christopher Wiley08725a82016-05-18 16:32:44 -070045import android.os.INetworkManagementService;
Christopher Wiley279eca32016-05-20 13:23:10 -070046import android.os.RemoteException;
Christopher Wiley08725a82016-05-18 16:32:44 -070047import android.os.test.TestLooper;
Christopher Wiley9bc0df22016-05-25 13:57:27 -070048import android.support.test.filters.SmallTest;
49import android.support.test.runner.AndroidJUnit4;
Christopher Wiley08725a82016-05-18 16:32:44 -070050
51import org.junit.Before;
52import org.junit.Test;
Christopher Wiley9bc0df22016-05-25 13:57:27 -070053import org.junit.runner.RunWith;
Christopher Wiley279eca32016-05-20 13:23:10 -070054import org.mockito.InOrder;
Christopher Wiley08725a82016-05-18 16:32:44 -070055import org.mockito.Mock;
56import org.mockito.MockitoAnnotations;
57
Christopher Wiley9bc0df22016-05-25 13:57:27 -070058@RunWith(AndroidJUnit4.class)
59@SmallTest
Mitchell Wills4622c2d2016-05-23 16:40:10 -070060public class TetherInterfaceStateMachineTest {
Christopher Wiley08725a82016-05-18 16:32:44 -070061 private static final String IFACE_NAME = "testnet1";
Christopher Wiley279eca32016-05-20 13:23:10 -070062 private static final String UPSTREAM_IFACE = "upstream0";
63 private static final String UPSTREAM_IFACE2 = "upstream1";
Christopher Wiley08725a82016-05-18 16:32:44 -070064
65 @Mock private INetworkManagementService mNMService;
66 @Mock private INetworkStatsService mStatsService;
67 @Mock private IControlsTethering mTetherHelper;
Christopher Wiley279eca32016-05-20 13:23:10 -070068 @Mock private InterfaceConfiguration mInterfaceConfiguration;
Lorenzo Colitti5bce5a12016-10-28 17:45:55 +090069 @Mock private IPv6TetheringInterfaceServices mIPv6TetheringInterfaceServices;
Erik Kline7747fd42017-05-12 16:52:48 +090070 @Mock private SharedLog mSharedLog;
Christopher Wiley08725a82016-05-18 16:32:44 -070071
72 private final TestLooper mLooper = new TestLooper();
Mitchell Wills4622c2d2016-05-23 16:40:10 -070073 private TetherInterfaceStateMachine mTestedSm;
Christopher Wiley08725a82016-05-18 16:32:44 -070074
Christopher Wileycd0cfbb2016-05-31 14:43:08 -070075 private void initStateMachine(int interfaceType) throws Exception {
Erik Kline7747fd42017-05-12 16:52:48 +090076 mTestedSm = new TetherInterfaceStateMachine(
77 IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog,
Lorenzo Colitti5bce5a12016-10-28 17:45:55 +090078 mNMService, mStatsService, mTetherHelper, mIPv6TetheringInterfaceServices);
Christopher Wiley279eca32016-05-20 13:23:10 -070079 mTestedSm.start();
80 // Starting the state machine always puts us in a consistent state and notifies
81 // the test of the world that we've changed from an unknown to available state.
82 mLooper.dispatchAll();
83 reset(mNMService, mStatsService, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -070084 when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
Christopher Wiley279eca32016-05-20 13:23:10 -070085 }
86
Christopher Wileycd0cfbb2016-05-31 14:43:08 -070087 private void initTetheredStateMachine(int interfaceType, String upstreamIface) throws Exception {
88 initStateMachine(interfaceType);
Erik Klineea9cc482017-03-10 19:35:34 +090089 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
Christopher Wiley279eca32016-05-20 13:23:10 -070090 if (upstreamIface != null) {
91 dispatchTetherConnectionChanged(upstreamIface);
92 }
93 reset(mNMService, mStatsService, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -070094 when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
Christopher Wiley279eca32016-05-20 13:23:10 -070095 }
96
Christopher Wileye90e0a72016-05-31 10:44:35 -070097 @Before public void setUp() throws Exception {
Christopher Wiley08725a82016-05-18 16:32:44 -070098 MockitoAnnotations.initMocks(this);
Erik Kline7747fd42017-05-12 16:52:48 +090099 when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
Christopher Wiley279eca32016-05-20 13:23:10 -0700100 }
101
102 @Test
103 public void startsOutAvailable() {
Christopher Wileycd0cfbb2016-05-31 14:43:08 -0700104 mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(),
Erik Kline7747fd42017-05-12 16:52:48 +0900105 TETHERING_BLUETOOTH, mSharedLog, mNMService, mStatsService, mTetherHelper,
Lorenzo Colitti5bce5a12016-10-28 17:45:55 +0900106 mIPv6TetheringInterfaceServices);
Christopher Wiley08725a82016-05-18 16:32:44 -0700107 mTestedSm.start();
Christopher Wiley279eca32016-05-20 13:23:10 -0700108 mLooper.dispatchAll();
Erik Klineab6439b2017-06-06 19:24:21 +0900109 verify(mTetherHelper).updateInterfaceState(
110 mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
111 verify(mTetherHelper).updateLinkProperties(eq(mTestedSm), any(LinkProperties.class));
Christopher Wiley279eca32016-05-20 13:23:10 -0700112 verifyNoMoreInteractions(mTetherHelper, mNMService, mStatsService);
Christopher Wiley08725a82016-05-18 16:32:44 -0700113 }
114
115 @Test
Christopher Wileyf972edc2016-05-23 16:17:30 -0700116 public void shouldDoNothingUntilRequested() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900117 initStateMachine(TETHERING_BLUETOOTH);
Christopher Wiley08725a82016-05-18 16:32:44 -0700118 final int [] NOOP_COMMANDS = {
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700119 TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED,
120 TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR,
121 TetherInterfaceStateMachine.CMD_IP_FORWARDING_DISABLE_ERROR,
122 TetherInterfaceStateMachine.CMD_START_TETHERING_ERROR,
123 TetherInterfaceStateMachine.CMD_STOP_TETHERING_ERROR,
124 TetherInterfaceStateMachine.CMD_SET_DNS_FORWARDERS_ERROR,
125 TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED
Christopher Wiley08725a82016-05-18 16:32:44 -0700126 };
127 for (int command : NOOP_COMMANDS) {
Christopher Wiley279eca32016-05-20 13:23:10 -0700128 // None of these commands should trigger us to request action from
Christopher Wiley08725a82016-05-18 16:32:44 -0700129 // the rest of the system.
Christopher Wiley279eca32016-05-20 13:23:10 -0700130 dispatchCommand(command);
131 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley08725a82016-05-18 16:32:44 -0700132 }
133 }
134
Christopher Wiley279eca32016-05-20 13:23:10 -0700135 @Test
Christopher Wileyf972edc2016-05-23 16:17:30 -0700136 public void handlesImmediateInterfaceDown() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900137 initStateMachine(TETHERING_BLUETOOTH);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700138
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700139 dispatchCommand(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
Erik Klineab6439b2017-06-06 19:24:21 +0900140 verify(mTetherHelper).updateInterfaceState(
141 mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
142 verify(mTetherHelper).updateLinkProperties(eq(mTestedSm), any(LinkProperties.class));
Christopher Wiley279eca32016-05-20 13:23:10 -0700143 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700144 }
145
146 @Test
Christopher Wileyf972edc2016-05-23 16:17:30 -0700147 public void canBeTethered() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900148 initStateMachine(TETHERING_BLUETOOTH);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700149
Erik Klineea9cc482017-03-10 19:35:34 +0900150 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
Christopher Wiley279eca32016-05-20 13:23:10 -0700151 InOrder inOrder = inOrder(mTetherHelper, mNMService);
Christopher Wiley279eca32016-05-20 13:23:10 -0700152 inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
Erik Klineab6439b2017-06-06 19:24:21 +0900153 inOrder.verify(mTetherHelper).updateInterfaceState(
154 mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
155 inOrder.verify(mTetherHelper).updateLinkProperties(
156 eq(mTestedSm), any(LinkProperties.class));
Christopher Wiley279eca32016-05-20 13:23:10 -0700157 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700158 }
159
160 @Test
161 public void canUnrequestTethering() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900162 initTetheredStateMachine(TETHERING_BLUETOOTH, null);
Christopher Wiley279eca32016-05-20 13:23:10 -0700163
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700164 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
Christopher Wiley279eca32016-05-20 13:23:10 -0700165 InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700166 inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
Erik Klineab6439b2017-06-06 19:24:21 +0900167 inOrder.verify(mTetherHelper).updateInterfaceState(
168 mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
169 inOrder.verify(mTetherHelper).updateLinkProperties(
170 eq(mTestedSm), any(LinkProperties.class));
Christopher Wiley279eca32016-05-20 13:23:10 -0700171 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700172 }
173
174 @Test
Christopher Wileyf972edc2016-05-23 16:17:30 -0700175 public void canBeTetheredAsUsb() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900176 initStateMachine(TETHERING_USB);
Christopher Wiley279eca32016-05-20 13:23:10 -0700177
Erik Klineea9cc482017-03-10 19:35:34 +0900178 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
Christopher Wiley279eca32016-05-20 13:23:10 -0700179 InOrder inOrder = inOrder(mTetherHelper, mNMService);
Christopher Wiley279eca32016-05-20 13:23:10 -0700180 inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
181 inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
Christopher Wiley279eca32016-05-20 13:23:10 -0700182 inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
Erik Klineab6439b2017-06-06 19:24:21 +0900183 inOrder.verify(mTetherHelper).updateInterfaceState(
184 mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
185 inOrder.verify(mTetherHelper).updateLinkProperties(
186 eq(mTestedSm), any(LinkProperties.class));
Christopher Wiley279eca32016-05-20 13:23:10 -0700187 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700188 }
189
190 @Test
191 public void handlesFirstUpstreamChange() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900192 initTetheredStateMachine(TETHERING_BLUETOOTH, null);
Christopher Wiley279eca32016-05-20 13:23:10 -0700193
Erik Klineab6439b2017-06-06 19:24:21 +0900194 // Telling the state machine about its upstream interface triggers
195 // a little more configuration.
Christopher Wiley279eca32016-05-20 13:23:10 -0700196 dispatchTetherConnectionChanged(UPSTREAM_IFACE);
197 InOrder inOrder = inOrder(mNMService);
198 inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE);
199 inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
200 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700201 }
202
203 @Test
204 public void handlesChangingUpstream() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900205 initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
Christopher Wiley279eca32016-05-20 13:23:10 -0700206
207 dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
208 InOrder inOrder = inOrder(mNMService, mStatsService);
209 inOrder.verify(mStatsService).forceUpdate();
210 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
211 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
212 inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
213 inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
214 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700215 }
216
217 @Test
Erik Klinea954be92017-02-13 17:12:02 +0900218 public void handlesChangingUpstreamNatFailure() throws Exception {
219 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
220
221 doThrow(RemoteException.class).when(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
222
223 dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
224 InOrder inOrder = inOrder(mNMService, mStatsService);
225 inOrder.verify(mStatsService).forceUpdate();
226 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
227 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
228 inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
Erik Kline8ea45482017-02-13 17:28:53 +0900229 inOrder.verify(mStatsService).forceUpdate();
230 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
231 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE2);
Erik Klinea954be92017-02-13 17:12:02 +0900232 }
233
234 @Test
235 public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception {
236 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
237
238 doThrow(RemoteException.class).when(mNMService).startInterfaceForwarding(
239 IFACE_NAME, UPSTREAM_IFACE2);
240
241 dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
242 InOrder inOrder = inOrder(mNMService, mStatsService);
243 inOrder.verify(mStatsService).forceUpdate();
244 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
245 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
246 inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
247 inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
Erik Kline8ea45482017-02-13 17:28:53 +0900248 inOrder.verify(mStatsService).forceUpdate();
249 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
250 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE2);
Erik Klinea954be92017-02-13 17:12:02 +0900251 }
252
253 @Test
Christopher Wiley279eca32016-05-20 13:23:10 -0700254 public void canUnrequestTetheringWithUpstream() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900255 initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
Christopher Wiley279eca32016-05-20 13:23:10 -0700256
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700257 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
Christopher Wiley279eca32016-05-20 13:23:10 -0700258 InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
259 inOrder.verify(mStatsService).forceUpdate();
260 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
261 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
262 inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
Erik Klineab6439b2017-06-06 19:24:21 +0900263 inOrder.verify(mTetherHelper).updateInterfaceState(
264 mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
265 inOrder.verify(mTetherHelper).updateLinkProperties(
266 eq(mTestedSm), any(LinkProperties.class));
Christopher Wiley279eca32016-05-20 13:23:10 -0700267 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700268 }
269
Christopher Wileyf972edc2016-05-23 16:17:30 -0700270 @Test
271 public void interfaceDownLeadsToUnavailable() throws Exception {
272 for (boolean shouldThrow : new boolean[]{true, false}) {
Erik Klinea954be92017-02-13 17:12:02 +0900273 initTetheredStateMachine(TETHERING_USB, null);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700274
275 if (shouldThrow) {
276 doThrow(RemoteException.class).when(mNMService).untetherInterface(IFACE_NAME);
277 }
278 dispatchCommand(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700279 InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700280 usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
281 usbTeardownOrder.verify(mNMService).setInterfaceConfig(
282 IFACE_NAME, mInterfaceConfiguration);
Erik Klineab6439b2017-06-06 19:24:21 +0900283 usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
284 mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
285 usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
286 eq(mTestedSm), any(LinkProperties.class));
Christopher Wileyf972edc2016-05-23 16:17:30 -0700287 }
288 }
289
290 @Test
291 public void usbShouldBeTornDownOnTetherError() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900292 initStateMachine(TETHERING_USB);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700293
294 doThrow(RemoteException.class).when(mNMService).tetherInterface(IFACE_NAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900295 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700296 InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700297 usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
298 usbTeardownOrder.verify(mNMService).setInterfaceConfig(
299 IFACE_NAME, mInterfaceConfiguration);
Erik Klineab6439b2017-06-06 19:24:21 +0900300 usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
301 mTestedSm, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
302 usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
303 eq(mTestedSm), any(LinkProperties.class));
Christopher Wileyf972edc2016-05-23 16:17:30 -0700304 }
305
306 @Test
307 public void shouldTearDownUsbOnUpstreamError() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900308 initTetheredStateMachine(TETHERING_USB, null);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700309
310 doThrow(RemoteException.class).when(mNMService).enableNat(anyString(), anyString());
311 dispatchTetherConnectionChanged(UPSTREAM_IFACE);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700312 InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700313 usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
314 usbTeardownOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
Erik Klineab6439b2017-06-06 19:24:21 +0900315 usbTeardownOrder.verify(mTetherHelper).updateInterfaceState(
316 mTestedSm, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
317 usbTeardownOrder.verify(mTetherHelper).updateLinkProperties(
318 eq(mTestedSm), any(LinkProperties.class));
Christopher Wileyf972edc2016-05-23 16:17:30 -0700319 }
Christopher Wiley279eca32016-05-20 13:23:10 -0700320
Erik Kline624bf3d2017-02-14 15:55:00 +0900321 @Test
322 public void ignoresDuplicateUpstreamNotifications() throws Exception {
323 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
324
325 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
326
327 for (int i = 0; i < 5; i++) {
328 dispatchTetherConnectionChanged(UPSTREAM_IFACE);
329 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
330 }
331 }
332
Christopher Wiley279eca32016-05-20 13:23:10 -0700333 /**
334 * Send a command to the state machine under test, and run the event loop to idle.
335 *
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700336 * @param command One of the TetherInterfaceStateMachine.CMD_* constants.
Erik Klineea9cc482017-03-10 19:35:34 +0900337 * @param obj An additional argument to pass.
338 */
339 private void dispatchCommand(int command, int arg1) {
340 mTestedSm.sendMessage(command, arg1);
341 mLooper.dispatchAll();
342 }
343
344 /**
345 * Send a command to the state machine under test, and run the event loop to idle.
346 *
347 * @param command One of the TetherInterfaceStateMachine.CMD_* constants.
Christopher Wiley279eca32016-05-20 13:23:10 -0700348 */
349 private void dispatchCommand(int command) {
350 mTestedSm.sendMessage(command);
351 mLooper.dispatchAll();
352 }
353
354 /**
355 * Special override to tell the state machine that the upstream interface has changed.
356 *
357 * @see #dispatchCommand(int)
358 * @param upstreamIface String name of upstream interface (or null)
359 */
360 private void dispatchTetherConnectionChanged(String upstreamIface) {
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700361 mTestedSm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
362 upstreamIface);
Christopher Wiley279eca32016-05-20 13:23:10 -0700363 mLooper.dispatchAll();
Christopher Wiley08725a82016-05-18 16:32:44 -0700364 }
Lorenzo Colitti5bce5a12016-10-28 17:45:55 +0900365}