ConnectivityServiceTest.java revision fb878b66b9456f8fee2bcb1076263852d207949d
1/*
2 * Copyright (C) 2012 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;
18
19import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
20import static android.net.ConnectivityManager.TYPE_MOBILE;
21import static android.net.ConnectivityManager.TYPE_WIFI;
22import static android.net.ConnectivityManager.getNetworkTypeName;
23import static android.net.NetworkStateTracker.EVENT_STATE_CHANGED;
24import static com.google.testing.littlemock.LittleMock.anyInt;
25import static com.google.testing.littlemock.LittleMock.createCaptor;
26import static com.google.testing.littlemock.LittleMock.doNothing;
27import static com.google.testing.littlemock.LittleMock.doReturn;
28import static com.google.testing.littlemock.LittleMock.doThrow;
29import static com.google.testing.littlemock.LittleMock.eq;
30import static com.google.testing.littlemock.LittleMock.isA;
31import static com.google.testing.littlemock.LittleMock.mock;
32import static com.google.testing.littlemock.LittleMock.reset;
33import static com.google.testing.littlemock.LittleMock.verify;
34
35import android.content.Context;
36import android.net.INetworkPolicyManager;
37import android.net.INetworkStatsService;
38import android.net.LinkProperties;
39import android.net.NetworkConfig;
40import android.net.NetworkInfo;
41import android.net.NetworkInfo.DetailedState;
42import android.net.NetworkStateTracker;
43import android.net.RouteInfo;
44import android.os.Handler;
45import android.os.INetworkManagementService;
46import android.test.AndroidTestCase;
47import android.test.suitebuilder.annotation.LargeTest;
48import android.util.Log;
49import android.util.LogPrinter;
50
51import com.google.testing.littlemock.ArgumentCaptor;
52
53import java.net.InetAddress;
54import java.util.concurrent.Future;
55
56/**
57 * Tests for {@link ConnectivityService}.
58 */
59@LargeTest
60public class ConnectivityServiceTest extends AndroidTestCase {
61    private static final String TAG = "ConnectivityServiceTest";
62
63    private static final String MOBILE_IFACE = "rmnet3";
64    private static final String WIFI_IFACE = "wlan6";
65
66    private static final RouteInfo MOBILE_ROUTE_V4 = RouteInfo.makeHostRoute(parse("10.0.0.33"));
67    private static final RouteInfo MOBILE_ROUTE_V6 = RouteInfo.makeHostRoute(parse("fd00::33"));
68
69    private static final RouteInfo WIFI_ROUTE_V4 = RouteInfo.makeHostRoute(
70            parse("192.168.0.66"), parse("192.168.0.1"));
71    private static final RouteInfo WIFI_ROUTE_V6 = RouteInfo.makeHostRoute(
72            parse("fd00::66"), parse("fd00::"));
73
74    private INetworkManagementService mNetManager;
75    private INetworkStatsService mStatsService;
76    private INetworkPolicyManager mPolicyService;
77    private ConnectivityService.NetworkFactory mNetFactory;
78
79    private BroadcastInterceptingContext mServiceContext;
80    private ConnectivityService mService;
81
82    private MockNetwork mMobile;
83    private MockNetwork mWifi;
84
85    private Handler mTrackerHandler;
86
87    private static class MockNetwork {
88        public NetworkStateTracker tracker;
89        public NetworkInfo info;
90        public LinkProperties link;
91
92        public MockNetwork(int type) {
93            tracker = mock(NetworkStateTracker.class);
94            info = new NetworkInfo(type, -1, getNetworkTypeName(type), null);
95            link = new LinkProperties();
96        }
97
98        public void doReturnDefaults() {
99            // TODO: eventually CS should make defensive copies
100            doReturn(new NetworkInfo(info)).when(tracker).getNetworkInfo();
101            doReturn(new LinkProperties(link)).when(tracker).getLinkProperties();
102
103            // fallback to default TCP buffers
104            doReturn("").when(tracker).getTcpBufferSizesPropName();
105        }
106    }
107
108    @Override
109    public void setUp() throws Exception {
110        super.setUp();
111
112        mServiceContext = new BroadcastInterceptingContext(getContext());
113
114        mNetManager = mock(INetworkManagementService.class);
115        mStatsService = mock(INetworkStatsService.class);
116        mPolicyService = mock(INetworkPolicyManager.class);
117        mNetFactory = mock(ConnectivityService.NetworkFactory.class);
118
119        mMobile = new MockNetwork(TYPE_MOBILE);
120        mWifi = new MockNetwork(TYPE_WIFI);
121
122        // omit most network trackers
123        doThrow(new IllegalArgumentException("Not supported in test environment"))
124                .when(mNetFactory).createTracker(anyInt(), isA(NetworkConfig.class));
125
126        doReturn(mMobile.tracker)
127                .when(mNetFactory).createTracker(eq(TYPE_MOBILE), isA(NetworkConfig.class));
128        doReturn(mWifi.tracker)
129                .when(mNetFactory).createTracker(eq(TYPE_WIFI), isA(NetworkConfig.class));
130
131        final ArgumentCaptor<Handler> trackerHandler = createCaptor();
132        doNothing().when(mMobile.tracker)
133                .startMonitoring(isA(Context.class), trackerHandler.capture());
134
135        mService = new ConnectivityService(
136                mServiceContext, mNetManager, mStatsService, mPolicyService, mNetFactory);
137        mService.systemReady();
138
139        mTrackerHandler = trackerHandler.getValue();
140        mTrackerHandler.getLooper().setMessageLogging(new LogPrinter(Log.INFO, TAG));
141    }
142
143    @Override
144    public void tearDown() throws Exception {
145        super.tearDown();
146    }
147
148    public void testMobileConnectedAddedRoutes() throws Exception {
149        Future<?> nextConnBroadcast;
150
151        // bring up mobile network
152        mMobile.info.setDetailedState(DetailedState.CONNECTED, null, null);
153        mMobile.link.setInterfaceName(MOBILE_IFACE);
154        mMobile.link.addRoute(MOBILE_ROUTE_V4);
155        mMobile.link.addRoute(MOBILE_ROUTE_V6);
156        mMobile.doReturnDefaults();
157
158        nextConnBroadcast = mServiceContext.nextBroadcastIntent(CONNECTIVITY_ACTION_IMMEDIATE);
159        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
160        nextConnBroadcast.get();
161
162        // verify that both routes were added and DNS was flushed
163        verify(mNetManager).addRoute(eq(MOBILE_IFACE), eq(MOBILE_ROUTE_V4));
164        verify(mNetManager).addRoute(eq(MOBILE_IFACE), eq(MOBILE_ROUTE_V6));
165        verify(mNetManager).flushInterfaceDnsCache(MOBILE_IFACE);
166
167    }
168
169    public void testMobileWifiHandoff() throws Exception {
170        Future<?> nextConnBroadcast;
171
172        // bring up mobile network
173        mMobile.info.setDetailedState(DetailedState.CONNECTED, null, null);
174        mMobile.link.setInterfaceName(MOBILE_IFACE);
175        mMobile.link.addRoute(MOBILE_ROUTE_V4);
176        mMobile.link.addRoute(MOBILE_ROUTE_V6);
177        mMobile.doReturnDefaults();
178
179        nextConnBroadcast = mServiceContext.nextBroadcastIntent(CONNECTIVITY_ACTION_IMMEDIATE);
180        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
181        nextConnBroadcast.get();
182
183        reset(mNetManager);
184
185        // now bring up wifi network
186        mWifi.info.setDetailedState(DetailedState.CONNECTED, null, null);
187        mWifi.link.setInterfaceName(WIFI_IFACE);
188        mWifi.link.addRoute(WIFI_ROUTE_V4);
189        mWifi.link.addRoute(WIFI_ROUTE_V6);
190        mWifi.doReturnDefaults();
191
192        // expect that mobile will be torn down
193        doReturn(true).when(mMobile.tracker).teardown();
194
195        nextConnBroadcast = mServiceContext.nextBroadcastIntent(CONNECTIVITY_ACTION_IMMEDIATE);
196        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mWifi.info).sendToTarget();
197        nextConnBroadcast.get();
198
199        // verify that wifi routes added, and teardown requested
200        verify(mNetManager).addRoute(eq(WIFI_IFACE), eq(WIFI_ROUTE_V4));
201        verify(mNetManager).addRoute(eq(WIFI_IFACE), eq(WIFI_ROUTE_V6));
202        verify(mNetManager).flushInterfaceDnsCache(WIFI_IFACE);
203        verify(mMobile.tracker).teardown();
204
205        reset(mNetManager, mMobile.tracker);
206
207        // tear down mobile network, as requested
208        mMobile.info.setDetailedState(DetailedState.DISCONNECTED, null, null);
209        mMobile.link.clear();
210        mMobile.doReturnDefaults();
211
212        nextConnBroadcast = mServiceContext.nextBroadcastIntent(CONNECTIVITY_ACTION_IMMEDIATE);
213        mTrackerHandler.obtainMessage(EVENT_STATE_CHANGED, mMobile.info).sendToTarget();
214        nextConnBroadcast.get();
215
216        verify(mNetManager).removeRoute(eq(MOBILE_IFACE), eq(MOBILE_ROUTE_V4));
217        verify(mNetManager).removeRoute(eq(MOBILE_IFACE), eq(MOBILE_ROUTE_V6));
218
219    }
220
221    private static InetAddress parse(String addr) {
222        return InetAddress.parseNumericAddress(addr);
223    }
224}
225