blob: caf1a5583a5b17492ed2f0a6e91ea590d714ecec [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
Christopher Wileyf972edc2016-05-23 16:17:30 -070019import static org.mockito.Matchers.anyString;
20import static org.mockito.Mockito.doThrow;
Christopher Wiley279eca32016-05-20 13:23:10 -070021import static org.mockito.Mockito.inOrder;
22import static org.mockito.Mockito.reset;
23import static org.mockito.Mockito.verify;
Christopher Wiley08725a82016-05-18 16:32:44 -070024import static org.mockito.Mockito.verifyNoMoreInteractions;
Christopher Wiley279eca32016-05-20 13:23:10 -070025import static org.mockito.Mockito.when;
Christopher Wiley08725a82016-05-18 16:32:44 -070026
Christopher Wileye90e0a72016-05-31 10:44:35 -070027import static android.net.ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
28import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
29import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
30import static android.net.ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
Erik Klinea954be92017-02-13 17:12:02 +090031import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
32import static android.net.ConnectivityManager.TETHERING_USB;
33import static android.net.ConnectivityManager.TETHERING_WIFI;
Christopher Wileye90e0a72016-05-31 10:44:35 -070034import static com.android.server.connectivity.tethering.IControlsTethering.STATE_AVAILABLE;
Erik Klineea9cc482017-03-10 19:35:34 +090035import static com.android.server.connectivity.tethering.IControlsTethering.STATE_LOCAL_HOTSPOT;
Christopher Wileye90e0a72016-05-31 10:44:35 -070036import static com.android.server.connectivity.tethering.IControlsTethering.STATE_TETHERED;
37import static com.android.server.connectivity.tethering.IControlsTethering.STATE_UNAVAILABLE;
38
Christopher Wileycd0cfbb2016-05-31 14:43:08 -070039import android.net.ConnectivityManager;
Christopher Wiley08725a82016-05-18 16:32:44 -070040import android.net.INetworkStatsService;
Christopher Wiley279eca32016-05-20 13:23:10 -070041import android.net.InterfaceConfiguration;
Christopher Wiley08725a82016-05-18 16:32:44 -070042import android.os.INetworkManagementService;
Christopher Wiley279eca32016-05-20 13:23:10 -070043import android.os.RemoteException;
Christopher Wiley08725a82016-05-18 16:32:44 -070044import android.os.test.TestLooper;
Christopher Wiley9bc0df22016-05-25 13:57:27 -070045import android.support.test.filters.SmallTest;
46import android.support.test.runner.AndroidJUnit4;
Christopher Wiley08725a82016-05-18 16:32:44 -070047
48import org.junit.Before;
49import org.junit.Test;
Christopher Wiley9bc0df22016-05-25 13:57:27 -070050import org.junit.runner.RunWith;
Christopher Wiley279eca32016-05-20 13:23:10 -070051import org.mockito.InOrder;
Christopher Wiley08725a82016-05-18 16:32:44 -070052import org.mockito.Mock;
53import org.mockito.MockitoAnnotations;
54
Christopher Wiley9bc0df22016-05-25 13:57:27 -070055@RunWith(AndroidJUnit4.class)
56@SmallTest
Mitchell Wills4622c2d2016-05-23 16:40:10 -070057public class TetherInterfaceStateMachineTest {
Christopher Wiley08725a82016-05-18 16:32:44 -070058 private static final String IFACE_NAME = "testnet1";
Christopher Wiley279eca32016-05-20 13:23:10 -070059 private static final String UPSTREAM_IFACE = "upstream0";
60 private static final String UPSTREAM_IFACE2 = "upstream1";
Christopher Wiley08725a82016-05-18 16:32:44 -070061
62 @Mock private INetworkManagementService mNMService;
63 @Mock private INetworkStatsService mStatsService;
64 @Mock private IControlsTethering mTetherHelper;
Christopher Wiley279eca32016-05-20 13:23:10 -070065 @Mock private InterfaceConfiguration mInterfaceConfiguration;
Lorenzo Colitti5bce5a12016-10-28 17:45:55 +090066 @Mock private IPv6TetheringInterfaceServices mIPv6TetheringInterfaceServices;
Christopher Wiley08725a82016-05-18 16:32:44 -070067
68 private final TestLooper mLooper = new TestLooper();
Mitchell Wills4622c2d2016-05-23 16:40:10 -070069 private TetherInterfaceStateMachine mTestedSm;
Christopher Wiley08725a82016-05-18 16:32:44 -070070
Christopher Wileycd0cfbb2016-05-31 14:43:08 -070071 private void initStateMachine(int interfaceType) throws Exception {
72 mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(), interfaceType,
Lorenzo Colitti5bce5a12016-10-28 17:45:55 +090073 mNMService, mStatsService, mTetherHelper, mIPv6TetheringInterfaceServices);
Christopher Wiley279eca32016-05-20 13:23:10 -070074 mTestedSm.start();
75 // Starting the state machine always puts us in a consistent state and notifies
76 // the test of the world that we've changed from an unknown to available state.
77 mLooper.dispatchAll();
78 reset(mNMService, mStatsService, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -070079 when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
Christopher Wiley279eca32016-05-20 13:23:10 -070080 }
81
Christopher Wileycd0cfbb2016-05-31 14:43:08 -070082 private void initTetheredStateMachine(int interfaceType, String upstreamIface) throws Exception {
83 initStateMachine(interfaceType);
Erik Klineea9cc482017-03-10 19:35:34 +090084 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
Christopher Wiley279eca32016-05-20 13:23:10 -070085 if (upstreamIface != null) {
86 dispatchTetherConnectionChanged(upstreamIface);
87 }
88 reset(mNMService, mStatsService, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -070089 when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
Christopher Wiley279eca32016-05-20 13:23:10 -070090 }
91
Christopher Wileye90e0a72016-05-31 10:44:35 -070092 @Before public void setUp() throws Exception {
Christopher Wiley08725a82016-05-18 16:32:44 -070093 MockitoAnnotations.initMocks(this);
Christopher Wiley279eca32016-05-20 13:23:10 -070094 }
95
96 @Test
97 public void startsOutAvailable() {
Christopher Wileycd0cfbb2016-05-31 14:43:08 -070098 mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(),
Erik Klinea954be92017-02-13 17:12:02 +090099 TETHERING_BLUETOOTH, mNMService, mStatsService, mTetherHelper,
Lorenzo Colitti5bce5a12016-10-28 17:45:55 +0900100 mIPv6TetheringInterfaceServices);
Christopher Wiley08725a82016-05-18 16:32:44 -0700101 mTestedSm.start();
Christopher Wiley279eca32016-05-20 13:23:10 -0700102 mLooper.dispatchAll();
Christopher Wileye90e0a72016-05-31 10:44:35 -0700103 verify(mTetherHelper).notifyInterfaceStateChange(
104 IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
Christopher Wiley279eca32016-05-20 13:23:10 -0700105 verifyNoMoreInteractions(mTetherHelper, mNMService, mStatsService);
Christopher Wiley08725a82016-05-18 16:32:44 -0700106 }
107
108 @Test
Christopher Wileyf972edc2016-05-23 16:17:30 -0700109 public void shouldDoNothingUntilRequested() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900110 initStateMachine(TETHERING_BLUETOOTH);
Christopher Wiley08725a82016-05-18 16:32:44 -0700111 final int [] NOOP_COMMANDS = {
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700112 TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED,
113 TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR,
114 TetherInterfaceStateMachine.CMD_IP_FORWARDING_DISABLE_ERROR,
115 TetherInterfaceStateMachine.CMD_START_TETHERING_ERROR,
116 TetherInterfaceStateMachine.CMD_STOP_TETHERING_ERROR,
117 TetherInterfaceStateMachine.CMD_SET_DNS_FORWARDERS_ERROR,
118 TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED
Christopher Wiley08725a82016-05-18 16:32:44 -0700119 };
120 for (int command : NOOP_COMMANDS) {
Christopher Wiley279eca32016-05-20 13:23:10 -0700121 // None of these commands should trigger us to request action from
Christopher Wiley08725a82016-05-18 16:32:44 -0700122 // the rest of the system.
Christopher Wiley279eca32016-05-20 13:23:10 -0700123 dispatchCommand(command);
124 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley08725a82016-05-18 16:32:44 -0700125 }
126 }
127
Christopher Wiley279eca32016-05-20 13:23:10 -0700128 @Test
Christopher Wileyf972edc2016-05-23 16:17:30 -0700129 public void handlesImmediateInterfaceDown() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900130 initStateMachine(TETHERING_BLUETOOTH);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700131
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700132 dispatchCommand(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700133 verify(mTetherHelper).notifyInterfaceStateChange(
134 IFACE_NAME, mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
Christopher Wiley279eca32016-05-20 13:23:10 -0700135 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700136 }
137
138 @Test
Christopher Wileyf972edc2016-05-23 16:17:30 -0700139 public void canBeTethered() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900140 initStateMachine(TETHERING_BLUETOOTH);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700141
Erik Klineea9cc482017-03-10 19:35:34 +0900142 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
Christopher Wiley279eca32016-05-20 13:23:10 -0700143 InOrder inOrder = inOrder(mTetherHelper, mNMService);
Christopher Wiley279eca32016-05-20 13:23:10 -0700144 inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700145 inOrder.verify(mTetherHelper).notifyInterfaceStateChange(
146 IFACE_NAME, mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
Christopher Wiley279eca32016-05-20 13:23:10 -0700147 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700148 }
149
150 @Test
151 public void canUnrequestTethering() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900152 initTetheredStateMachine(TETHERING_BLUETOOTH, null);
Christopher Wiley279eca32016-05-20 13:23:10 -0700153
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700154 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
Christopher Wiley279eca32016-05-20 13:23:10 -0700155 InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700156 inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700157 inOrder.verify(mTetherHelper).notifyInterfaceStateChange(
158 IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
Christopher Wiley279eca32016-05-20 13:23:10 -0700159 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700160 }
161
162 @Test
Christopher Wileyf972edc2016-05-23 16:17:30 -0700163 public void canBeTetheredAsUsb() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900164 initStateMachine(TETHERING_USB);
Christopher Wiley279eca32016-05-20 13:23:10 -0700165
Erik Klineea9cc482017-03-10 19:35:34 +0900166 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
Christopher Wiley279eca32016-05-20 13:23:10 -0700167 InOrder inOrder = inOrder(mTetherHelper, mNMService);
Christopher Wiley279eca32016-05-20 13:23:10 -0700168 inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
169 inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
Christopher Wiley279eca32016-05-20 13:23:10 -0700170 inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700171 inOrder.verify(mTetherHelper).notifyInterfaceStateChange(
172 IFACE_NAME, mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
Christopher Wiley279eca32016-05-20 13:23:10 -0700173 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700174 }
175
176 @Test
177 public void handlesFirstUpstreamChange() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900178 initTetheredStateMachine(TETHERING_BLUETOOTH, null);
Christopher Wiley279eca32016-05-20 13:23:10 -0700179
180 // Telling the state machine about its upstream interface triggers a little more configuration.
181 dispatchTetherConnectionChanged(UPSTREAM_IFACE);
182 InOrder inOrder = inOrder(mNMService);
183 inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE);
184 inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
185 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700186 }
187
188 @Test
189 public void handlesChangingUpstream() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900190 initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
Christopher Wiley279eca32016-05-20 13:23:10 -0700191
192 dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
193 InOrder inOrder = inOrder(mNMService, mStatsService);
194 inOrder.verify(mStatsService).forceUpdate();
195 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
196 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
197 inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
198 inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
199 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700200 }
201
202 @Test
Erik Klinea954be92017-02-13 17:12:02 +0900203 public void handlesChangingUpstreamNatFailure() throws Exception {
204 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
205
206 doThrow(RemoteException.class).when(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
207
208 dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
209 InOrder inOrder = inOrder(mNMService, mStatsService);
210 inOrder.verify(mStatsService).forceUpdate();
211 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
212 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
213 inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
Erik Kline8ea45482017-02-13 17:28:53 +0900214 inOrder.verify(mStatsService).forceUpdate();
215 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
216 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE2);
Erik Klinea954be92017-02-13 17:12:02 +0900217 }
218
219 @Test
220 public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception {
221 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
222
223 doThrow(RemoteException.class).when(mNMService).startInterfaceForwarding(
224 IFACE_NAME, UPSTREAM_IFACE2);
225
226 dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
227 InOrder inOrder = inOrder(mNMService, mStatsService);
228 inOrder.verify(mStatsService).forceUpdate();
229 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
230 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
231 inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
232 inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
Erik Kline8ea45482017-02-13 17:28:53 +0900233 inOrder.verify(mStatsService).forceUpdate();
234 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
235 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE2);
Erik Klinea954be92017-02-13 17:12:02 +0900236 }
237
238 @Test
Christopher Wiley279eca32016-05-20 13:23:10 -0700239 public void canUnrequestTetheringWithUpstream() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900240 initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
Christopher Wiley279eca32016-05-20 13:23:10 -0700241
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700242 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
Christopher Wiley279eca32016-05-20 13:23:10 -0700243 InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
244 inOrder.verify(mStatsService).forceUpdate();
245 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
246 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
247 inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700248 inOrder.verify(mTetherHelper).notifyInterfaceStateChange(
249 IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
Christopher Wiley279eca32016-05-20 13:23:10 -0700250 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700251 }
252
Christopher Wileyf972edc2016-05-23 16:17:30 -0700253 @Test
254 public void interfaceDownLeadsToUnavailable() throws Exception {
255 for (boolean shouldThrow : new boolean[]{true, false}) {
Erik Klinea954be92017-02-13 17:12:02 +0900256 initTetheredStateMachine(TETHERING_USB, null);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700257
258 if (shouldThrow) {
259 doThrow(RemoteException.class).when(mNMService).untetherInterface(IFACE_NAME);
260 }
261 dispatchCommand(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700262 InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700263 usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
264 usbTeardownOrder.verify(mNMService).setInterfaceConfig(
265 IFACE_NAME, mInterfaceConfiguration);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700266 usbTeardownOrder.verify(mTetherHelper).notifyInterfaceStateChange(
267 IFACE_NAME, mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700268 }
269 }
270
271 @Test
272 public void usbShouldBeTornDownOnTetherError() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900273 initStateMachine(TETHERING_USB);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700274
275 doThrow(RemoteException.class).when(mNMService).tetherInterface(IFACE_NAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900276 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700277 InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700278 usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
279 usbTeardownOrder.verify(mNMService).setInterfaceConfig(
280 IFACE_NAME, mInterfaceConfiguration);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700281 usbTeardownOrder.verify(mTetherHelper).notifyInterfaceStateChange(
282 IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700283 }
284
285 @Test
286 public void shouldTearDownUsbOnUpstreamError() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900287 initTetheredStateMachine(TETHERING_USB, null);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700288
289 doThrow(RemoteException.class).when(mNMService).enableNat(anyString(), anyString());
290 dispatchTetherConnectionChanged(UPSTREAM_IFACE);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700291 InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700292 usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
293 usbTeardownOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700294 usbTeardownOrder.verify(mTetherHelper).notifyInterfaceStateChange(
295 IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700296 }
Christopher Wiley279eca32016-05-20 13:23:10 -0700297
Erik Kline624bf3d2017-02-14 15:55:00 +0900298 @Test
299 public void ignoresDuplicateUpstreamNotifications() throws Exception {
300 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
301
302 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
303
304 for (int i = 0; i < 5; i++) {
305 dispatchTetherConnectionChanged(UPSTREAM_IFACE);
306 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
307 }
308 }
309
Christopher Wiley279eca32016-05-20 13:23:10 -0700310 /**
311 * Send a command to the state machine under test, and run the event loop to idle.
312 *
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700313 * @param command One of the TetherInterfaceStateMachine.CMD_* constants.
Erik Klineea9cc482017-03-10 19:35:34 +0900314 * @param obj An additional argument to pass.
315 */
316 private void dispatchCommand(int command, int arg1) {
317 mTestedSm.sendMessage(command, arg1);
318 mLooper.dispatchAll();
319 }
320
321 /**
322 * Send a command to the state machine under test, and run the event loop to idle.
323 *
324 * @param command One of the TetherInterfaceStateMachine.CMD_* constants.
Christopher Wiley279eca32016-05-20 13:23:10 -0700325 */
326 private void dispatchCommand(int command) {
327 mTestedSm.sendMessage(command);
328 mLooper.dispatchAll();
329 }
330
331 /**
332 * Special override to tell the state machine that the upstream interface has changed.
333 *
334 * @see #dispatchCommand(int)
335 * @param upstreamIface String name of upstream interface (or null)
336 */
337 private void dispatchTetherConnectionChanged(String upstreamIface) {
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700338 mTestedSm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
339 upstreamIface);
Christopher Wiley279eca32016-05-20 13:23:10 -0700340 mLooper.dispatchAll();
Christopher Wiley08725a82016-05-18 16:32:44 -0700341 }
Lorenzo Colitti5bce5a12016-10-28 17:45:55 +0900342}