WifiDetailPreferenceControllerTest.java revision 0bde06cd594840fb4aa49fe1b034a3859f36c246
1/*
2 * Copyright (C) 2017 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 */
16package com.android.settings.wifi.details;
17
18import static com.google.common.truth.Truth.assertThat;
19
20import static org.mockito.Matchers.any;
21import static org.mockito.Mockito.doNothing;
22import static org.mockito.Mockito.inOrder;
23import static org.mockito.Mockito.never;
24import static org.mockito.Mockito.reset;
25import static org.mockito.Mockito.times;
26import static org.mockito.Mockito.verify;
27import static org.mockito.Mockito.when;
28
29import android.app.Activity;
30import android.content.Context;
31import android.content.Intent;
32import android.graphics.drawable.Drawable;
33import android.net.ConnectivityManager;
34import android.net.ConnectivityManager.NetworkCallback;
35import android.net.IpPrefix;
36import android.net.LinkAddress;
37import android.net.LinkProperties;
38import android.net.Network;
39import android.net.NetworkBadging;
40import android.net.NetworkCapabilities;
41import android.net.NetworkInfo;
42import android.net.NetworkRequest;
43import android.net.RouteInfo;
44import android.net.wifi.WifiConfiguration;
45import android.net.wifi.WifiInfo;
46import android.net.wifi.WifiManager;
47import android.os.Handler;
48import android.support.v7.preference.Preference;
49import android.support.v7.preference.PreferenceCategory;
50import android.support.v7.preference.PreferenceScreen;
51import android.view.View;
52import android.view.View.OnClickListener;
53import android.widget.Button;
54
55import com.android.internal.logging.nano.MetricsProto;
56import com.android.settings.R;
57import com.android.settings.SettingsRobolectricTestRunner;
58import com.android.settings.TestConfig;
59import com.android.settings.applications.LayoutPreference;
60import com.android.settings.core.instrumentation.MetricsFeatureProvider;
61import com.android.settings.core.lifecycle.Lifecycle;
62import com.android.settings.vpn2.ConnectivityManagerWrapperImpl;
63import com.android.settings.wifi.WifiDetailPreference;
64import com.android.settingslib.wifi.AccessPoint;
65
66import org.junit.Before;
67import org.junit.Test;
68import org.junit.runner.RunWith;
69import org.mockito.Answers;
70import org.mockito.ArgumentCaptor;
71import org.mockito.Captor;
72import org.mockito.InOrder;
73import org.mockito.Mock;
74import org.mockito.MockitoAnnotations;
75import org.robolectric.RuntimeEnvironment;
76import org.robolectric.annotation.Config;
77
78import java.net.Inet4Address;
79import java.net.Inet6Address;
80import java.net.InetAddress;
81import java.net.UnknownHostException;
82import java.util.Arrays;
83import java.util.List;
84import java.util.stream.Collectors;
85
86@RunWith(SettingsRobolectricTestRunner.class)
87@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
88public class WifiDetailPreferenceControllerTest {
89
90    private static final int LEVEL = 1;
91    private static final int RSSI = -55;
92    private static final int LINK_SPEED = 123;
93    private static final String MAC_ADDRESS = WifiInfo.DEFAULT_MAC_ADDRESS;
94    private static final String SECURITY = "None";
95
96    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
97    private PreferenceScreen mockScreen;
98
99    @Mock private AccessPoint mockAccessPoint;
100    @Mock private Activity mockActivity;
101    @Mock private ConnectivityManager mockConnectivityManager;
102    @Mock private ConnectivityManagerWrapperImpl mockConnectivityManagerWrapper;
103    @Mock private Network mockNetwork;
104    @Mock private NetworkInfo mockNetworkInfo;
105    @Mock private WifiConfiguration mockWifiConfig;
106    @Mock private WifiInfo mockWifiInfo;
107    @Mock private WifiNetworkDetailsFragment mockFragment;
108    @Mock private WifiManager mockWifiManager;
109    @Mock private MetricsFeatureProvider mockMetricsFeatureProvider;
110
111    @Mock private Preference mockConnectionDetailPref;
112    @Mock private LayoutPreference mockButtonsPref;
113    @Mock private Button mockSignInButton;
114    @Mock private WifiDetailPreference mockSignalStrengthPref;
115    @Mock private WifiDetailPreference mockLinkSpeedPref;
116    @Mock private WifiDetailPreference mockFrequencyPref;
117    @Mock private WifiDetailPreference mockSecurityPref;
118    @Mock private WifiDetailPreference mockMacAddressPref;
119    @Mock private WifiDetailPreference mockIpAddressPref;
120    @Mock private WifiDetailPreference mockGatewayPref;
121    @Mock private WifiDetailPreference mockSubnetPref;
122    @Mock private WifiDetailPreference mockDnsPref;
123    @Mock private Button mockForgetButton;
124    @Mock private PreferenceCategory mockIpv6Category;
125    @Mock private WifiDetailPreference mockIpv6AddressesPref;
126
127    @Captor private ArgumentCaptor<NetworkCallback> mCallbackCaptor;
128    @Captor private ArgumentCaptor<View.OnClickListener> mForgetClickListener;
129    @Captor private ArgumentCaptor<Preference> mIpv6AddressCaptor;
130
131    private Context mContext = RuntimeEnvironment.application;
132    private Lifecycle mLifecycle;
133    private LinkProperties mLinkProperties;
134    private WifiDetailPreferenceController mController;
135
136    // This class exists so that these values can be made static final. They can't be static final
137    // members of the test class, because any attempt to call IpPrefix or RouteInfo constructors
138    // during static initialization of the test class results in NoSuchMethorError being thrown
139    // when the test is run.
140    private static class Constants {
141        static final int IPV4_PREFIXLEN = 25;
142        static final LinkAddress IPV4_ADDR;
143        static final Inet4Address IPV4_GATEWAY;
144        static final RouteInfo IPV4_DEFAULT;
145        static final RouteInfo IPV4_SUBNET;
146        static final LinkAddress IPV6_LINKLOCAL;
147        static final LinkAddress IPV6_GLOBAL1;
148        static final LinkAddress IPV6_GLOBAL2;
149        static final InetAddress IPV4_DNS1;
150        static final InetAddress IPV4_DNS2;
151        static final InetAddress IPV6_DNS;
152
153        private static LinkAddress ipv6LinkAddress(String addr) throws UnknownHostException {
154            return new LinkAddress(InetAddress.getByName(addr), 64);
155        }
156
157        private static LinkAddress ipv4LinkAddress(String addr, int prefixlen)
158                throws UnknownHostException {
159            return new LinkAddress(InetAddress.getByName(addr), prefixlen);
160        }
161
162        static {
163            try {
164                // We create our test constants in these roundabout ways because the robolectric
165                // shadows don't contain NetworkUtils.parseNumericAddress and other utility methods,
166                // so the easy ways to do things fail with NoSuchMethodError.
167                IPV4_ADDR = ipv4LinkAddress("192.0.2.2", IPV4_PREFIXLEN);
168                IPV4_GATEWAY = (Inet4Address) InetAddress.getByName("192.0.2.127");
169
170                final Inet4Address any4 = (Inet4Address) InetAddress.getByName("0.0.0.0");
171                IpPrefix subnet = new IpPrefix(IPV4_ADDR.getAddress(), IPV4_PREFIXLEN);
172                IPV4_SUBNET = new RouteInfo(subnet, any4);
173                IPV4_DEFAULT = new RouteInfo(new IpPrefix(any4, 0), IPV4_GATEWAY);
174
175                IPV6_LINKLOCAL = ipv6LinkAddress("fe80::211:25ff:fef8:7cb2%1");
176                IPV6_GLOBAL1 = ipv6LinkAddress("2001:db8:1::211:25ff:fef8:7cb2");
177                IPV6_GLOBAL2 = ipv6LinkAddress("2001:db8:1::3dfe:8902:f98f:739d");
178
179                IPV4_DNS1 = InetAddress.getByName("8.8.8.8");
180                IPV4_DNS2 = InetAddress.getByName("8.8.4.4");
181                IPV6_DNS = InetAddress.getByName("2001:4860:4860::64");
182            } catch (UnknownHostException e) {
183                throw new RuntimeException("Invalid hardcoded IP addresss: " + e);
184            }
185        }
186    }
187
188    @Before
189    public void setUp() {
190        MockitoAnnotations.initMocks(this);
191
192        mLifecycle = new Lifecycle();
193
194        when(mockAccessPoint.getConfig()).thenReturn(mockWifiConfig);
195        when(mockAccessPoint.getLevel()).thenReturn(LEVEL);
196        when(mockAccessPoint.getSecurityString(false)).thenReturn(SECURITY);
197
198        when(mockConnectivityManagerWrapper.getConnectivityManager())
199                .thenReturn(mockConnectivityManager);
200        when(mockConnectivityManager.getNetworkInfo(any(Network.class)))
201                .thenReturn(mockNetworkInfo);
202        doNothing().when(mockConnectivityManagerWrapper).registerNetworkCallback(
203                any(NetworkRequest.class), mCallbackCaptor.capture(), any(Handler.class));
204        doNothing().when(mockForgetButton).setOnClickListener(mForgetClickListener.capture());
205
206        when(mockWifiInfo.getLinkSpeed()).thenReturn(LINK_SPEED);
207        when(mockWifiInfo.getRssi()).thenReturn(RSSI);
208        when(mockWifiInfo.getMacAddress()).thenReturn(MAC_ADDRESS);
209        when(mockWifiManager.getConnectionInfo()).thenReturn(mockWifiInfo);
210
211        when(mockWifiManager.getCurrentNetwork()).thenReturn(mockNetwork);
212        mLinkProperties = new LinkProperties();
213        when(mockConnectivityManager.getLinkProperties(mockNetwork)).thenReturn(mLinkProperties);
214
215        when(mockFragment.getActivity()).thenReturn(mockActivity);
216
217        setupMockedPreferenceScreen();
218        mController = newWifiDetailPreferenceController();
219    }
220
221    private WifiDetailPreferenceController newWifiDetailPreferenceController() {
222        return new WifiDetailPreferenceController(
223                mockAccessPoint,
224                mockConnectivityManagerWrapper,
225                mContext,
226                mockFragment,
227                null,  // Handler
228                mLifecycle,
229                mockWifiManager,
230                mockMetricsFeatureProvider);
231    }
232
233    private void setupMockedPreferenceScreen() {
234        when(mockScreen.getPreferenceManager().getContext()).thenReturn(mContext);
235
236        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_CONNECTION_DETAIL_PREF))
237                .thenReturn(mockConnectionDetailPref);
238        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_BUTTONS_PREF))
239                .thenReturn(mockButtonsPref);
240        when(mockButtonsPref.findViewById(R.id.left_button))
241                .thenReturn(mockForgetButton);
242        when(mockButtonsPref.findViewById(R.id.right_button))
243                .thenReturn(mockSignInButton);
244        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SIGNAL_STRENGTH_PREF))
245                .thenReturn(mockSignalStrengthPref);
246        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_LINK_SPEED))
247                .thenReturn(mockLinkSpeedPref);
248        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_FREQUENCY_PREF))
249                .thenReturn(mockFrequencyPref);
250        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SECURITY_PREF))
251                .thenReturn(mockSecurityPref);
252        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_MAC_ADDRESS_PREF))
253                .thenReturn(mockMacAddressPref);
254        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_IP_ADDRESS_PREF))
255                .thenReturn(mockIpAddressPref);
256        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_GATEWAY_PREF))
257                .thenReturn(mockGatewayPref);
258        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SUBNET_MASK_PREF))
259                .thenReturn(mockSubnetPref);
260        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_DNS_PREF))
261                .thenReturn(mockDnsPref);
262        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_IPV6_CATEGORY))
263                .thenReturn(mockIpv6Category);
264        when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_IPV6_ADDRESSES_PREF))
265                .thenReturn(mockIpv6AddressesPref);
266    }
267
268    @Test
269    public void isAvailable_shouldAlwaysReturnTrue() {
270        mController.displayPreference(mockScreen);
271
272        assertThat(mController.isAvailable()).isTrue();
273    }
274
275    @Test
276    public void securityPreference_stringShouldBeSet() {
277        mController.displayPreference(mockScreen);
278
279        verify(mockSecurityPref).setDetailText(SECURITY);
280    }
281
282    @Test
283    public void latestWifiInfo_shouldBeFetchedInDisplayPreference() {
284        mController.displayPreference(mockScreen);
285
286        verify(mockWifiManager, times(1)).getConnectionInfo();
287    }
288
289    @Test
290    public void latestNetworkInfo_shouldBeFetchedInDisplayPreference() {
291        mController.displayPreference(mockScreen);
292
293        verify(mockConnectivityManager, times(1)).getNetworkInfo(any(Network.class));
294    }
295
296    @Test
297    public void networkCallback_shouldBeRegisteredOnResume() {
298        mController.onResume();
299
300        verify(mockConnectivityManagerWrapper, times(1)).registerNetworkCallback(
301                any(NetworkRequest.class), mCallbackCaptor.capture(), any(Handler.class));
302    }
303
304    @Test
305    public void networkCallback_shouldBeUnregisteredOnPause() {
306        mController.onResume();
307        mController.onPause();
308
309        verify(mockConnectivityManager, times(1)).unregisterNetworkCallback(
310                mCallbackCaptor.getValue());
311    }
312
313    @Test
314    public void connectionDetailPref_shouldHaveIconSet() {
315        Drawable expectedIcon =
316                NetworkBadging.getWifiIcon(LEVEL, NetworkBadging.BADGING_NONE, mContext.getTheme());
317
318        mController.displayPreference(mockScreen);
319
320        verify(mockConnectionDetailPref).setIcon(expectedIcon);
321    }
322
323    @Test
324    public void connectionDetailPref_shouldHaveTitleSet() {
325        String summary = "summary";
326        when(mockAccessPoint.getSettingsSummary()).thenReturn(summary);
327
328        mController.displayPreference(mockScreen);
329
330        verify(mockConnectionDetailPref).setTitle(summary);
331    }
332
333    @Test
334    public void signalStrengthPref_shouldHaveIconSet() {
335        mController.displayPreference(mockScreen);
336
337        verify(mockSignalStrengthPref).setIcon(any(Drawable.class));
338    }
339
340    @Test
341    public void signalStrengthPref_shouldHaveDetailTextSet() {
342        String expectedStrength =
343                mContext.getResources().getStringArray(R.array.wifi_signal)[LEVEL];
344
345        mController.displayPreference(mockScreen);
346
347        verify(mockSignalStrengthPref).setDetailText(expectedStrength);
348    }
349
350    @Test
351    public void linkSpeedPref_shouldHaveDetailTextSet() {
352        String expectedLinkSpeed = mContext.getString(R.string.link_speed, LINK_SPEED);
353
354        mController.displayPreference(mockScreen);
355
356        verify(mockLinkSpeedPref).setDetailText(expectedLinkSpeed);
357    }
358
359    @Test
360    public void linkSpeedPref_shouldNotShowIfNotSet() {
361        when(mockWifiInfo.getLinkSpeed()).thenReturn(-1);
362
363        mController.displayPreference(mockScreen);
364
365        verify(mockLinkSpeedPref).setVisible(false);
366    }
367
368    @Test
369    public void macAddressPref_shouldHaveDetailTextSet() {
370        mController.displayPreference(mockScreen);
371
372        verify(mockMacAddressPref).setDetailText(MAC_ADDRESS);
373    }
374
375    @Test
376    public void ipAddressPref_shouldHaveDetailTextSet() {
377        mLinkProperties.addLinkAddress(Constants.IPV4_ADDR);
378
379        mController.displayPreference(mockScreen);
380
381        verify(mockIpAddressPref).setDetailText(Constants.IPV4_ADDR.getAddress().getHostAddress());
382    }
383
384    @Test
385    public void gatewayAndSubnet_shouldHaveDetailTextSet() {
386        mLinkProperties.addLinkAddress(Constants.IPV4_ADDR);
387        mLinkProperties.addRoute(Constants.IPV4_DEFAULT);
388        mLinkProperties.addRoute(Constants.IPV4_SUBNET);
389
390        mController.displayPreference(mockScreen);
391
392        verify(mockSubnetPref).setDetailText("255.255.255.128");
393        verify(mockGatewayPref).setDetailText("192.0.2.127");
394    }
395
396    @Test
397    public void dnsServersPref_shouldHaveDetailTextSet() throws UnknownHostException {
398        mLinkProperties.addDnsServer(InetAddress.getByAddress(new byte[]{8,8,4,4}));
399        mLinkProperties.addDnsServer(InetAddress.getByAddress(new byte[]{8,8,8,8}));
400
401        mController.displayPreference(mockScreen);
402
403        verify(mockDnsPref).setDetailText("8.8.4.4,8.8.8.8");
404    }
405
406    @Test
407    public void noCurrentNetwork_shouldFinishActivity() {
408        // If WifiManager#getCurrentNetwork() returns null, then the network is neither connected
409        // nor connecting and WifiStateMachine has not reached L2ConnectedState.
410        when(mockWifiManager.getCurrentNetwork()).thenReturn(null);
411
412        mController.displayPreference(mockScreen);
413
414        verify(mockActivity).finish();
415    }
416
417    @Test
418    public void noLinkProperties_allIpDetailsHidden() {
419        when(mockConnectivityManager.getLinkProperties(mockNetwork)).thenReturn(null);
420        reset(mockIpv6Category, mockIpAddressPref, mockSubnetPref, mockGatewayPref,
421                mockDnsPref);
422
423        mController.displayPreference(mockScreen);
424
425        verify(mockIpv6Category).setVisible(false);
426        verify(mockIpAddressPref).setVisible(false);
427        verify(mockSubnetPref).setVisible(false);
428        verify(mockGatewayPref).setVisible(false);
429        verify(mockDnsPref).setVisible(false);
430        verify(mockIpv6Category, never()).setVisible(true);
431        verify(mockIpAddressPref, never()).setVisible(true);
432        verify(mockSubnetPref, never()).setVisible(true);
433        verify(mockGatewayPref, never()).setVisible(true);
434        verify(mockDnsPref, never()).setVisible(true);
435    }
436
437    // Convenience method to convert a LinkAddress to a string without a prefix length.
438    private String asString(LinkAddress l) {
439        return l.getAddress().getHostAddress();
440    }
441
442    // Pretend that the NetworkCallback was triggered with a new copy of lp. We need to create a
443    // new copy because the code only updates if !mLinkProperties.equals(lp).
444    private void updateLinkProperties(LinkProperties lp) {
445        mCallbackCaptor.getValue().onLinkPropertiesChanged(mockNetwork, new LinkProperties(lp));
446    }
447
448    private void verifyDisplayedIpv6Addresses(InOrder inOrder, LinkAddress... addresses) {
449        String text = Arrays.stream(addresses)
450                .map(address -> asString(address))
451                .collect(Collectors.joining("\n"));
452        inOrder.verify(mockIpv6AddressesPref).setSummary(text);
453    }
454
455    @Test
456    public void onLinkPropertiesChanged_updatesFields() {
457        mController.displayPreference(mockScreen);
458        mController.onResume();
459
460        InOrder inOrder = inOrder(mockIpAddressPref, mockGatewayPref, mockSubnetPref,
461                mockDnsPref, mockIpv6Category, mockIpv6AddressesPref);
462
463        LinkProperties lp = new LinkProperties();
464
465        lp.addLinkAddress(Constants.IPV6_LINKLOCAL);
466        updateLinkProperties(lp);
467        verifyDisplayedIpv6Addresses(inOrder, Constants.IPV6_LINKLOCAL);
468        inOrder.verify(mockIpv6Category).setVisible(true);
469
470        lp.addRoute(Constants.IPV4_DEFAULT);
471        updateLinkProperties(lp);
472        inOrder.verify(mockGatewayPref).setDetailText(Constants.IPV4_GATEWAY.getHostAddress());
473        inOrder.verify(mockGatewayPref).setVisible(true);
474
475        lp.addLinkAddress(Constants.IPV4_ADDR);
476        lp.addRoute(Constants.IPV4_SUBNET);
477        updateLinkProperties(lp);
478        inOrder.verify(mockIpAddressPref).setDetailText(asString(Constants.IPV4_ADDR));
479        inOrder.verify(mockIpAddressPref).setVisible(true);
480        inOrder.verify(mockSubnetPref).setDetailText("255.255.255.128");
481        inOrder.verify(mockSubnetPref).setVisible(true);
482
483        lp.addLinkAddress(Constants.IPV6_GLOBAL1);
484        lp.addLinkAddress(Constants.IPV6_GLOBAL2);
485        updateLinkProperties(lp);
486        verifyDisplayedIpv6Addresses(inOrder,
487                Constants.IPV6_LINKLOCAL,
488                Constants.IPV6_GLOBAL1,
489                Constants.IPV6_GLOBAL2);
490
491        lp.removeLinkAddress(Constants.IPV6_GLOBAL1);
492        updateLinkProperties(lp);
493        verifyDisplayedIpv6Addresses(inOrder,
494                Constants.IPV6_LINKLOCAL,
495                Constants.IPV6_GLOBAL2);
496
497        lp.addDnsServer(Constants.IPV6_DNS);
498        updateLinkProperties(lp);
499        inOrder.verify(mockDnsPref, never()).setVisible(true);
500
501        lp.addDnsServer(Constants.IPV4_DNS1);
502        lp.addDnsServer(Constants.IPV4_DNS2);
503        updateLinkProperties(lp);
504        inOrder.verify(mockDnsPref).setDetailText(
505                Constants.IPV4_DNS1.getHostAddress() + "," +
506                Constants.IPV4_DNS2.getHostAddress());
507        inOrder.verify(mockDnsPref).setVisible(true);
508    }
509
510    @Test
511    public void canForgetNetwork_noNetwork() {
512        when(mockAccessPoint.getConfig()).thenReturn(null);
513
514        mController = newWifiDetailPreferenceController();
515        mController.displayPreference(mockScreen);
516
517        verify(mockForgetButton).setVisibility(View.INVISIBLE);
518    }
519
520    @Test
521    public void canForgetNetwork_ephemeral() {
522        when(mockWifiInfo.isEphemeral()).thenReturn(true);
523        when(mockAccessPoint.getConfig()).thenReturn(null);
524
525        mController.displayPreference(mockScreen);
526
527        verify(mockForgetButton).setVisibility(View.VISIBLE);
528    }
529
530    @Test
531    public void canForgetNetwork_saved() {
532        mController.displayPreference(mockScreen);
533
534        verify(mockForgetButton).setVisibility(View.VISIBLE);
535    }
536
537    @Test
538    public void forgetNetwork_ephemeral() {
539        String ssid = "ssid";
540        when(mockWifiInfo.isEphemeral()).thenReturn(true);
541        when(mockWifiInfo.getSSID()).thenReturn(ssid);
542
543        mController.displayPreference(mockScreen);
544        mForgetClickListener.getValue().onClick(null);
545
546        verify(mockWifiManager).disableEphemeralNetwork(ssid);
547        verify(mockMetricsFeatureProvider)
548                .action(mockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
549    }
550
551    @Test
552    public void forgetNetwork_saved() {
553        mockWifiConfig.networkId = 5;
554
555        mController.displayPreference(mockScreen);
556        mForgetClickListener.getValue().onClick(null);
557
558        verify(mockWifiManager).forget(mockWifiConfig.networkId, null);
559        verify(mockMetricsFeatureProvider)
560                .action(mockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
561    }
562
563    @Test
564    public void networkStateChangedIntent_shouldRefetchInfo() {
565        mController.displayPreference(mockScreen);
566        mController.onResume();
567
568        verify(mockConnectivityManager, times(1)).getNetworkInfo(any(Network.class));
569        verify(mockWifiManager, times(1)).getConnectionInfo();
570
571        mContext.sendBroadcast(new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION));
572
573        verify(mockConnectivityManager, times(2)).getNetworkInfo(any(Network.class));
574        verify(mockWifiManager, times(2)).getConnectionInfo();
575    }
576
577    @Test
578    public void rssiChangedIntent_shouldRefetchInfo() {
579        mController.displayPreference(mockScreen);
580        mController.onResume();
581
582        verify(mockConnectivityManager, times(1)).getNetworkInfo(any(Network.class));
583        verify(mockWifiManager, times(1)).getConnectionInfo();
584
585        mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION));
586
587        verify(mockConnectivityManager, times(2)).getNetworkInfo(any(Network.class));
588        verify(mockWifiManager, times(2)).getConnectionInfo();
589    }
590
591    @Test
592    public void networkDisconnectdState_shouldFinishActivity() {
593        mController.onResume();
594
595        when(mockConnectivityManager.getNetworkInfo(any(Network.class))).thenReturn(null);
596        mContext.sendBroadcast(new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION));
597
598        verify(mockActivity).finish();
599    }
600
601    @Test
602    public void networkOnLost_shouldFinishActivity() {
603        mController.displayPreference(mockScreen);
604        mController.onResume();
605
606        mCallbackCaptor.getValue().onLost(mockNetwork);
607
608        verify(mockActivity).finish();
609    }
610
611    @Test
612    public void ipv6AddressPref_shouldHaveHostAddressTextSet() {
613        mLinkProperties.addLinkAddress(Constants.IPV6_LINKLOCAL);
614        mLinkProperties.addLinkAddress(Constants.IPV6_GLOBAL1);
615        mLinkProperties.addLinkAddress(Constants.IPV6_GLOBAL2);
616
617        mController.displayPreference(mockScreen);
618
619        List <Preference> addrs = mIpv6AddressCaptor.getAllValues();
620
621        String expectedAddresses = String.join("\n",
622                asString(Constants.IPV6_LINKLOCAL),
623                asString(Constants.IPV6_GLOBAL1),
624                asString(Constants.IPV6_GLOBAL2));
625
626        verify(mockIpv6AddressesPref).setSummary(expectedAddresses);
627    }
628
629    @Test
630    public void ipv6AddressPref_shouldNotBeSelectable() {
631        mLinkProperties.addLinkAddress(Constants.IPV6_GLOBAL2);
632
633        mController.displayPreference(mockScreen);
634
635        assertThat(mockIpv6AddressesPref.isSelectable()).isFalse();
636    }
637
638    @Test
639    public void captivePortal_shouldShowSignInButton() {
640        InOrder inOrder = inOrder(mockSignInButton);
641
642        mController.displayPreference(mockScreen);
643        mController.onResume();
644
645        inOrder.verify(mockSignInButton).setVisibility(View.INVISIBLE);
646
647        NetworkCapabilities nc = new NetworkCapabilities();
648        nc.clearAll();
649        nc.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
650
651        NetworkCallback callback = mCallbackCaptor.getValue();
652        callback.onCapabilitiesChanged(mockNetwork, nc);
653        inOrder.verify(mockSignInButton).setVisibility(View.INVISIBLE);
654
655        nc = new NetworkCapabilities(nc);
656        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
657        callback.onCapabilitiesChanged(mockNetwork, nc);
658        inOrder.verify(mockSignInButton).setVisibility(View.VISIBLE);
659
660        nc = new NetworkCapabilities(nc);
661        nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
662        callback.onCapabilitiesChanged(mockNetwork, nc);
663        inOrder.verify(mockSignInButton).setVisibility(View.INVISIBLE);
664    }
665
666    @Test
667    public void testSignInButton_shouldStartCaptivePortalApp() {
668        mController.displayPreference(mockScreen);
669
670        ArgumentCaptor<OnClickListener> captor = ArgumentCaptor.forClass(OnClickListener.class);
671        verify(mockSignInButton).setOnClickListener(captor.capture());
672        captor.getValue().onClick(mockSignInButton);
673        verify(mockConnectivityManagerWrapper).startCaptivePortalApp(mockNetwork);
674    }
675
676    @Test
677    public void signInButtonVisible_buttonPanelShouldBeVisible() {
678        when(mockSignInButton.getVisibility()).thenReturn(View.VISIBLE);
679        when(mockForgetButton.getVisibility()).thenReturn(View.INVISIBLE);
680
681        mController.displayPreference(mockScreen);
682
683        verify(mockButtonsPref).setVisible(true);
684    }
685
686    @Test
687    public void forgetButtonVisible_buttonPanelShouldBeVisible() {
688        when(mockSignInButton.getVisibility()).thenReturn(View.INVISIBLE);
689        when(mockForgetButton.getVisibility()).thenReturn(View.VISIBLE);
690
691        mController.displayPreference(mockScreen);
692
693        verify(mockButtonsPref).setVisible(true);
694    }
695
696    @Test
697    public void neitherButtonVisible_buttonPanelShouldBeInvisible() {
698        when(mockSignInButton.getVisibility()).thenReturn(View.INVISIBLE);
699        when(mockForgetButton.getVisibility()).thenReturn(View.INVISIBLE);
700
701        mController.displayPreference(mockScreen);
702
703        verify(mockButtonsPref).setVisible(false);
704    }
705}
706