• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
16 
17 package com.android.server.connectivity;
18 
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertNull;
21 import static org.junit.Assert.assertTrue;
22 import static org.mockito.Mockito.any;
23 import static org.mockito.Mockito.eq;
24 import static org.mockito.Mockito.times;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.verifyNoMoreInteractions;
27 import static org.mockito.Mockito.when;
28 
29 import android.net.ConnectivityManager;
30 import android.net.InterfaceConfiguration;
31 import android.net.LinkAddress;
32 import android.net.LinkProperties;
33 import android.net.NetworkInfo;
34 import android.os.Handler;
35 import android.os.INetworkManagementService;
36 import android.os.test.TestLooper;
37 import android.support.test.filters.SmallTest;
38 import android.support.test.runner.AndroidJUnit4;
39 
40 import com.android.server.ConnectivityService;
41 
42 import org.junit.Before;
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 import org.mockito.ArgumentCaptor;
46 import org.mockito.Mock;
47 import org.mockito.MockitoAnnotations;
48 
49 @RunWith(AndroidJUnit4.class)
50 @SmallTest
51 public class Nat464XlatTest {
52 
53     static final String BASE_IFACE = "test0";
54     static final String STACKED_IFACE = "v4-test0";
55     static final LinkAddress ADDR = new LinkAddress("192.0.2.5/29");
56 
57     @Mock ConnectivityService mConnectivity;
58     @Mock INetworkManagementService mNms;
59     @Mock InterfaceConfiguration mConfig;
60     @Mock NetworkAgentInfo mNai;
61 
62     TestLooper mLooper;
63     Handler mHandler;
64 
makeNat464Xlat()65     Nat464Xlat makeNat464Xlat() {
66         return new Nat464Xlat(mNms, mNai);
67     }
68 
69     @Before
setUp()70     public void setUp() throws Exception {
71         mLooper = new TestLooper();
72         mHandler = new Handler(mLooper.getLooper());
73 
74         MockitoAnnotations.initMocks(this);
75 
76         mNai.linkProperties = new LinkProperties();
77         mNai.linkProperties.setInterfaceName(BASE_IFACE);
78         mNai.networkInfo = new NetworkInfo(null);
79         mNai.networkInfo.setType(ConnectivityManager.TYPE_WIFI);
80         when(mNai.connService()).thenReturn(mConnectivity);
81         when(mNai.handler()).thenReturn(mHandler);
82 
83         when(mNms.getInterfaceConfig(eq(STACKED_IFACE))).thenReturn(mConfig);
84         when(mConfig.getLinkAddress()).thenReturn(ADDR);
85     }
86 
87     @Test
testNormalStartAndStop()88     public void testNormalStartAndStop() throws Exception {
89         Nat464Xlat nat = makeNat464Xlat();
90         ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
91 
92         // ConnectivityService starts clat.
93         nat.start();
94 
95         verify(mNms).registerObserver(eq(nat));
96         verify(mNms).startClatd(eq(BASE_IFACE));
97 
98         // Stacked interface up notification arrives.
99         nat.interfaceLinkStateChanged(STACKED_IFACE, true);
100         mLooper.dispatchNext();
101 
102         verify(mNms).getInterfaceConfig(eq(STACKED_IFACE));
103         verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(false));
104         verify(mConnectivity).handleUpdateLinkProperties(eq(mNai), c.capture());
105         assertFalse(c.getValue().getStackedLinks().isEmpty());
106         assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
107         assertRunning(nat);
108 
109         // ConnectivityService stops clat (Network disconnects, IPv4 addr appears, ...).
110         nat.stop();
111 
112         verify(mNms).stopClatd(eq(BASE_IFACE));
113         verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(true));
114 
115         // Stacked interface removed notification arrives.
116         nat.interfaceRemoved(STACKED_IFACE);
117         mLooper.dispatchNext();
118 
119         verify(mNms).unregisterObserver(eq(nat));
120         verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture());
121         assertTrue(c.getValue().getStackedLinks().isEmpty());
122         assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
123         assertIdle(nat);
124 
125         verifyNoMoreInteractions(mNms, mConnectivity);
126     }
127 
128     @Test
testClatdCrashWhileRunning()129     public void testClatdCrashWhileRunning() throws Exception {
130         Nat464Xlat nat = makeNat464Xlat();
131         ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
132 
133         // ConnectivityService starts clat.
134         nat.start();
135 
136         verify(mNms).registerObserver(eq(nat));
137         verify(mNms).startClatd(eq(BASE_IFACE));
138 
139         // Stacked interface up notification arrives.
140         nat.interfaceLinkStateChanged(STACKED_IFACE, true);
141         mLooper.dispatchNext();
142 
143         verify(mNms).getInterfaceConfig(eq(STACKED_IFACE));
144         verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(false));
145         verify(mConnectivity, times(1)).handleUpdateLinkProperties(eq(mNai), c.capture());
146         assertFalse(c.getValue().getStackedLinks().isEmpty());
147         assertTrue(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
148         assertRunning(nat);
149 
150         // Stacked interface removed notification arrives (clatd crashed, ...).
151         nat.interfaceRemoved(STACKED_IFACE);
152         mLooper.dispatchNext();
153 
154         verify(mNms).unregisterObserver(eq(nat));
155         verify(mNms).stopClatd(eq(BASE_IFACE));
156         verify(mNms).setInterfaceIpv6NdOffload(eq(BASE_IFACE), eq(true));
157         verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture());
158         assertTrue(c.getValue().getStackedLinks().isEmpty());
159         assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
160         assertIdle(nat);
161 
162         // ConnectivityService stops clat: no-op.
163         nat.stop();
164 
165         verifyNoMoreInteractions(mNms, mConnectivity);
166     }
167 
168     @Test
testStopBeforeClatdStarts()169     public void testStopBeforeClatdStarts() throws Exception {
170         Nat464Xlat nat = makeNat464Xlat();
171 
172         // ConnectivityService starts clat.
173         nat.start();
174 
175         verify(mNms).registerObserver(eq(nat));
176         verify(mNms).startClatd(eq(BASE_IFACE));
177 
178         // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...)
179         nat.stop();
180 
181         verify(mNms).unregisterObserver(eq(nat));
182         verify(mNms).stopClatd(eq(BASE_IFACE));
183         assertIdle(nat);
184 
185         // In-flight interface up notification arrives: no-op
186         nat.interfaceLinkStateChanged(STACKED_IFACE, true);
187         mLooper.dispatchNext();
188 
189 
190         // Interface removed notification arrives after stopClatd() takes effect: no-op.
191         nat.interfaceRemoved(STACKED_IFACE);
192         mLooper.dispatchNext();
193 
194         assertIdle(nat);
195 
196         verifyNoMoreInteractions(mNms, mConnectivity);
197     }
198 
199     @Test
testStopAndClatdNeverStarts()200     public void testStopAndClatdNeverStarts() throws Exception {
201         Nat464Xlat nat = makeNat464Xlat();
202 
203         // ConnectivityService starts clat.
204         nat.start();
205 
206         verify(mNms).registerObserver(eq(nat));
207         verify(mNms).startClatd(eq(BASE_IFACE));
208 
209         // ConnectivityService immediately stops clat (Network disconnects, IPv4 addr appears, ...)
210         nat.stop();
211 
212         verify(mNms).unregisterObserver(eq(nat));
213         verify(mNms).stopClatd(eq(BASE_IFACE));
214         assertIdle(nat);
215 
216         verifyNoMoreInteractions(mNms, mConnectivity);
217     }
218 
assertIdle(Nat464Xlat nat)219     static void assertIdle(Nat464Xlat nat) {
220         assertTrue("Nat464Xlat was not IDLE", !nat.isStarted());
221     }
222 
assertRunning(Nat464Xlat nat)223     static void assertRunning(Nat464Xlat nat) {
224         assertTrue("Nat464Xlat was not RUNNING", nat.isRunning());
225     }
226 }
227