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