blob: 27e683c0881c9f3be22c50e9a70a43da314d6870 [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;
35import static com.android.server.connectivity.tethering.IControlsTethering.STATE_TETHERED;
36import static com.android.server.connectivity.tethering.IControlsTethering.STATE_UNAVAILABLE;
37
Christopher Wileycd0cfbb2016-05-31 14:43:08 -070038import android.net.ConnectivityManager;
Christopher Wiley08725a82016-05-18 16:32:44 -070039import android.net.INetworkStatsService;
Christopher Wiley279eca32016-05-20 13:23:10 -070040import android.net.InterfaceConfiguration;
Erik Kline7747fd42017-05-12 16:52:48 +090041import android.net.util.SharedLog;
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;
Erik Kline7747fd42017-05-12 16:52:48 +090067 @Mock private SharedLog mSharedLog;
Christopher Wiley08725a82016-05-18 16:32:44 -070068
69 private final TestLooper mLooper = new TestLooper();
Mitchell Wills4622c2d2016-05-23 16:40:10 -070070 private TetherInterfaceStateMachine mTestedSm;
Christopher Wiley08725a82016-05-18 16:32:44 -070071
Christopher Wileycd0cfbb2016-05-31 14:43:08 -070072 private void initStateMachine(int interfaceType) throws Exception {
Erik Kline7747fd42017-05-12 16:52:48 +090073 mTestedSm = new TetherInterfaceStateMachine(
74 IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog,
Lorenzo Colitti5bce5a12016-10-28 17:45:55 +090075 mNMService, mStatsService, mTetherHelper, mIPv6TetheringInterfaceServices);
Christopher Wiley279eca32016-05-20 13:23:10 -070076 mTestedSm.start();
77 // Starting the state machine always puts us in a consistent state and notifies
78 // the test of the world that we've changed from an unknown to available state.
79 mLooper.dispatchAll();
80 reset(mNMService, mStatsService, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -070081 when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
Christopher Wiley279eca32016-05-20 13:23:10 -070082 }
83
Christopher Wileycd0cfbb2016-05-31 14:43:08 -070084 private void initTetheredStateMachine(int interfaceType, String upstreamIface) throws Exception {
85 initStateMachine(interfaceType);
Erik Klineea9cc482017-03-10 19:35:34 +090086 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
Christopher Wiley279eca32016-05-20 13:23:10 -070087 if (upstreamIface != null) {
88 dispatchTetherConnectionChanged(upstreamIface);
89 }
90 reset(mNMService, mStatsService, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -070091 when(mNMService.getInterfaceConfig(IFACE_NAME)).thenReturn(mInterfaceConfiguration);
Christopher Wiley279eca32016-05-20 13:23:10 -070092 }
93
Christopher Wileye90e0a72016-05-31 10:44:35 -070094 @Before public void setUp() throws Exception {
Christopher Wiley08725a82016-05-18 16:32:44 -070095 MockitoAnnotations.initMocks(this);
Erik Kline7747fd42017-05-12 16:52:48 +090096 when(mSharedLog.forSubComponent(anyString())).thenReturn(mSharedLog);
Christopher Wiley279eca32016-05-20 13:23:10 -070097 }
98
99 @Test
100 public void startsOutAvailable() {
Christopher Wileycd0cfbb2016-05-31 14:43:08 -0700101 mTestedSm = new TetherInterfaceStateMachine(IFACE_NAME, mLooper.getLooper(),
Erik Kline7747fd42017-05-12 16:52:48 +0900102 TETHERING_BLUETOOTH, mSharedLog, mNMService, mStatsService, mTetherHelper,
Lorenzo Colitti5bce5a12016-10-28 17:45:55 +0900103 mIPv6TetheringInterfaceServices);
Christopher Wiley08725a82016-05-18 16:32:44 -0700104 mTestedSm.start();
Christopher Wiley279eca32016-05-20 13:23:10 -0700105 mLooper.dispatchAll();
Christopher Wileye90e0a72016-05-31 10:44:35 -0700106 verify(mTetherHelper).notifyInterfaceStateChange(
107 IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
Christopher Wiley279eca32016-05-20 13:23:10 -0700108 verifyNoMoreInteractions(mTetherHelper, mNMService, mStatsService);
Christopher Wiley08725a82016-05-18 16:32:44 -0700109 }
110
111 @Test
Christopher Wileyf972edc2016-05-23 16:17:30 -0700112 public void shouldDoNothingUntilRequested() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900113 initStateMachine(TETHERING_BLUETOOTH);
Christopher Wiley08725a82016-05-18 16:32:44 -0700114 final int [] NOOP_COMMANDS = {
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700115 TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED,
116 TetherInterfaceStateMachine.CMD_IP_FORWARDING_ENABLE_ERROR,
117 TetherInterfaceStateMachine.CMD_IP_FORWARDING_DISABLE_ERROR,
118 TetherInterfaceStateMachine.CMD_START_TETHERING_ERROR,
119 TetherInterfaceStateMachine.CMD_STOP_TETHERING_ERROR,
120 TetherInterfaceStateMachine.CMD_SET_DNS_FORWARDERS_ERROR,
121 TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED
Christopher Wiley08725a82016-05-18 16:32:44 -0700122 };
123 for (int command : NOOP_COMMANDS) {
Christopher Wiley279eca32016-05-20 13:23:10 -0700124 // None of these commands should trigger us to request action from
Christopher Wiley08725a82016-05-18 16:32:44 -0700125 // the rest of the system.
Christopher Wiley279eca32016-05-20 13:23:10 -0700126 dispatchCommand(command);
127 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley08725a82016-05-18 16:32:44 -0700128 }
129 }
130
Christopher Wiley279eca32016-05-20 13:23:10 -0700131 @Test
Christopher Wileyf972edc2016-05-23 16:17:30 -0700132 public void handlesImmediateInterfaceDown() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900133 initStateMachine(TETHERING_BLUETOOTH);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700134
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700135 dispatchCommand(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700136 verify(mTetherHelper).notifyInterfaceStateChange(
137 IFACE_NAME, mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
Christopher Wiley279eca32016-05-20 13:23:10 -0700138 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700139 }
140
141 @Test
Christopher Wileyf972edc2016-05-23 16:17:30 -0700142 public void canBeTethered() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900143 initStateMachine(TETHERING_BLUETOOTH);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700144
Erik Klineea9cc482017-03-10 19:35:34 +0900145 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
Christopher Wiley279eca32016-05-20 13:23:10 -0700146 InOrder inOrder = inOrder(mTetherHelper, mNMService);
Christopher Wiley279eca32016-05-20 13:23:10 -0700147 inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700148 inOrder.verify(mTetherHelper).notifyInterfaceStateChange(
149 IFACE_NAME, mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
Christopher Wiley279eca32016-05-20 13:23:10 -0700150 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700151 }
152
153 @Test
154 public void canUnrequestTethering() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900155 initTetheredStateMachine(TETHERING_BLUETOOTH, null);
Christopher Wiley279eca32016-05-20 13:23:10 -0700156
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700157 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
Christopher Wiley279eca32016-05-20 13:23:10 -0700158 InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700159 inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700160 inOrder.verify(mTetherHelper).notifyInterfaceStateChange(
161 IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
Christopher Wiley279eca32016-05-20 13:23:10 -0700162 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700163 }
164
165 @Test
Christopher Wileyf972edc2016-05-23 16:17:30 -0700166 public void canBeTetheredAsUsb() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900167 initStateMachine(TETHERING_USB);
Christopher Wiley279eca32016-05-20 13:23:10 -0700168
Erik Klineea9cc482017-03-10 19:35:34 +0900169 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
Christopher Wiley279eca32016-05-20 13:23:10 -0700170 InOrder inOrder = inOrder(mTetherHelper, mNMService);
Christopher Wiley279eca32016-05-20 13:23:10 -0700171 inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
172 inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
Christopher Wiley279eca32016-05-20 13:23:10 -0700173 inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700174 inOrder.verify(mTetherHelper).notifyInterfaceStateChange(
175 IFACE_NAME, mTestedSm, STATE_TETHERED, TETHER_ERROR_NO_ERROR);
Christopher Wiley279eca32016-05-20 13:23:10 -0700176 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700177 }
178
179 @Test
180 public void handlesFirstUpstreamChange() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900181 initTetheredStateMachine(TETHERING_BLUETOOTH, null);
Christopher Wiley279eca32016-05-20 13:23:10 -0700182
183 // Telling the state machine about its upstream interface triggers a little more configuration.
184 dispatchTetherConnectionChanged(UPSTREAM_IFACE);
185 InOrder inOrder = inOrder(mNMService);
186 inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE);
187 inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
188 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700189 }
190
191 @Test
192 public void handlesChangingUpstream() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900193 initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
Christopher Wiley279eca32016-05-20 13:23:10 -0700194
195 dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
196 InOrder inOrder = inOrder(mNMService, mStatsService);
197 inOrder.verify(mStatsService).forceUpdate();
198 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
199 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
200 inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
201 inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
202 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700203 }
204
205 @Test
Erik Klinea954be92017-02-13 17:12:02 +0900206 public void handlesChangingUpstreamNatFailure() throws Exception {
207 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
208
209 doThrow(RemoteException.class).when(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
210
211 dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
212 InOrder inOrder = inOrder(mNMService, mStatsService);
213 inOrder.verify(mStatsService).forceUpdate();
214 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
215 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
216 inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
Erik Kline8ea45482017-02-13 17:28:53 +0900217 inOrder.verify(mStatsService).forceUpdate();
218 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
219 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE2);
Erik Klinea954be92017-02-13 17:12:02 +0900220 }
221
222 @Test
223 public void handlesChangingUpstreamInterfaceForwardingFailure() throws Exception {
224 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
225
226 doThrow(RemoteException.class).when(mNMService).startInterfaceForwarding(
227 IFACE_NAME, UPSTREAM_IFACE2);
228
229 dispatchTetherConnectionChanged(UPSTREAM_IFACE2);
230 InOrder inOrder = inOrder(mNMService, mStatsService);
231 inOrder.verify(mStatsService).forceUpdate();
232 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
233 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
234 inOrder.verify(mNMService).enableNat(IFACE_NAME, UPSTREAM_IFACE2);
235 inOrder.verify(mNMService).startInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
Erik Kline8ea45482017-02-13 17:28:53 +0900236 inOrder.verify(mStatsService).forceUpdate();
237 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE2);
238 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE2);
Erik Klinea954be92017-02-13 17:12:02 +0900239 }
240
241 @Test
Christopher Wiley279eca32016-05-20 13:23:10 -0700242 public void canUnrequestTetheringWithUpstream() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900243 initTetheredStateMachine(TETHERING_BLUETOOTH, UPSTREAM_IFACE);
Christopher Wiley279eca32016-05-20 13:23:10 -0700244
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700245 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
Christopher Wiley279eca32016-05-20 13:23:10 -0700246 InOrder inOrder = inOrder(mNMService, mStatsService, mTetherHelper);
247 inOrder.verify(mStatsService).forceUpdate();
248 inOrder.verify(mNMService).stopInterfaceForwarding(IFACE_NAME, UPSTREAM_IFACE);
249 inOrder.verify(mNMService).disableNat(IFACE_NAME, UPSTREAM_IFACE);
250 inOrder.verify(mNMService).untetherInterface(IFACE_NAME);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700251 inOrder.verify(mTetherHelper).notifyInterfaceStateChange(
252 IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_NO_ERROR);
Christopher Wiley279eca32016-05-20 13:23:10 -0700253 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
Christopher Wiley279eca32016-05-20 13:23:10 -0700254 }
255
Christopher Wileyf972edc2016-05-23 16:17:30 -0700256 @Test
257 public void interfaceDownLeadsToUnavailable() throws Exception {
258 for (boolean shouldThrow : new boolean[]{true, false}) {
Erik Klinea954be92017-02-13 17:12:02 +0900259 initTetheredStateMachine(TETHERING_USB, null);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700260
261 if (shouldThrow) {
262 doThrow(RemoteException.class).when(mNMService).untetherInterface(IFACE_NAME);
263 }
264 dispatchCommand(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700265 InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700266 usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
267 usbTeardownOrder.verify(mNMService).setInterfaceConfig(
268 IFACE_NAME, mInterfaceConfiguration);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700269 usbTeardownOrder.verify(mTetherHelper).notifyInterfaceStateChange(
270 IFACE_NAME, mTestedSm, STATE_UNAVAILABLE, TETHER_ERROR_NO_ERROR);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700271 }
272 }
273
274 @Test
275 public void usbShouldBeTornDownOnTetherError() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900276 initStateMachine(TETHERING_USB);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700277
278 doThrow(RemoteException.class).when(mNMService).tetherInterface(IFACE_NAME);
Erik Klineea9cc482017-03-10 19:35:34 +0900279 dispatchCommand(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED, STATE_TETHERED);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700280 InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700281 usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
282 usbTeardownOrder.verify(mNMService).setInterfaceConfig(
283 IFACE_NAME, mInterfaceConfiguration);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700284 usbTeardownOrder.verify(mTetherHelper).notifyInterfaceStateChange(
285 IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_TETHER_IFACE_ERROR);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700286 }
287
288 @Test
289 public void shouldTearDownUsbOnUpstreamError() throws Exception {
Erik Klinea954be92017-02-13 17:12:02 +0900290 initTetheredStateMachine(TETHERING_USB, null);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700291
292 doThrow(RemoteException.class).when(mNMService).enableNat(anyString(), anyString());
293 dispatchTetherConnectionChanged(UPSTREAM_IFACE);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700294 InOrder usbTeardownOrder = inOrder(mNMService, mInterfaceConfiguration, mTetherHelper);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700295 usbTeardownOrder.verify(mInterfaceConfiguration).setInterfaceDown();
296 usbTeardownOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
Christopher Wileye90e0a72016-05-31 10:44:35 -0700297 usbTeardownOrder.verify(mTetherHelper).notifyInterfaceStateChange(
298 IFACE_NAME, mTestedSm, STATE_AVAILABLE, TETHER_ERROR_ENABLE_NAT_ERROR);
Christopher Wileyf972edc2016-05-23 16:17:30 -0700299 }
Christopher Wiley279eca32016-05-20 13:23:10 -0700300
Erik Kline624bf3d2017-02-14 15:55:00 +0900301 @Test
302 public void ignoresDuplicateUpstreamNotifications() throws Exception {
303 initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE);
304
305 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
306
307 for (int i = 0; i < 5; i++) {
308 dispatchTetherConnectionChanged(UPSTREAM_IFACE);
309 verifyNoMoreInteractions(mNMService, mStatsService, mTetherHelper);
310 }
311 }
312
Christopher Wiley279eca32016-05-20 13:23:10 -0700313 /**
314 * Send a command to the state machine under test, and run the event loop to idle.
315 *
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700316 * @param command One of the TetherInterfaceStateMachine.CMD_* constants.
Erik Klineea9cc482017-03-10 19:35:34 +0900317 * @param obj An additional argument to pass.
318 */
319 private void dispatchCommand(int command, int arg1) {
320 mTestedSm.sendMessage(command, arg1);
321 mLooper.dispatchAll();
322 }
323
324 /**
325 * Send a command to the state machine under test, and run the event loop to idle.
326 *
327 * @param command One of the TetherInterfaceStateMachine.CMD_* constants.
Christopher Wiley279eca32016-05-20 13:23:10 -0700328 */
329 private void dispatchCommand(int command) {
330 mTestedSm.sendMessage(command);
331 mLooper.dispatchAll();
332 }
333
334 /**
335 * Special override to tell the state machine that the upstream interface has changed.
336 *
337 * @see #dispatchCommand(int)
338 * @param upstreamIface String name of upstream interface (or null)
339 */
340 private void dispatchTetherConnectionChanged(String upstreamIface) {
Mitchell Wills4622c2d2016-05-23 16:40:10 -0700341 mTestedSm.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_CONNECTION_CHANGED,
342 upstreamIface);
Christopher Wiley279eca32016-05-20 13:23:10 -0700343 mLooper.dispatchAll();
Christopher Wiley08725a82016-05-18 16:32:44 -0700344 }
Lorenzo Colitti5bce5a12016-10-28 17:45:55 +0900345}