1 /*
2  * Copyright (C) 2020 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.vcn;
18 
19 import static android.net.IpSecManager.IpSecTunnelInterface;
20 
21 import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR;
22 
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.mockito.ArgumentMatchers.any;
28 import static org.mockito.ArgumentMatchers.eq;
29 import static org.mockito.Mockito.never;
30 import static org.mockito.Mockito.verify;
31 
32 import android.net.IpSecManager;
33 
34 import androidx.test.filters.SmallTest;
35 import androidx.test.runner.AndroidJUnit4;
36 
37 import org.junit.Before;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 
41 /** Tests for VcnGatewayConnection.DisconnectedState */
42 @RunWith(AndroidJUnit4.class)
43 @SmallTest
44 public class VcnGatewayConnectionDisconnectedStateTest extends VcnGatewayConnectionTestBase {
45     @Before
setUp()46     public void setUp() throws Exception {
47         super.setUp();
48 
49         final IpSecTunnelInterface tunnelIface =
50                 mContext.getSystemService(IpSecManager.class)
51                         .createIpSecTunnelInterface(
52                                 DUMMY_ADDR, DUMMY_ADDR, TEST_UNDERLYING_NETWORK_RECORD_1.network);
53         mGatewayConnection.setTunnelInterface(tunnelIface);
54 
55         // Don't need to transition to DisconnectedState because it is the starting state
56         mTestLooper.dispatchAll();
57     }
58 
59     @Test
testEnterWhileQuittingTriggersQuit()60     public void testEnterWhileQuittingTriggersQuit() throws Exception {
61         final VcnGatewayConnection vgc =
62                 new VcnGatewayConnection(
63                         mVcnContext,
64                         TEST_SUB_GRP,
65                         TEST_SUBSCRIPTION_SNAPSHOT,
66                         mConfig,
67                         mGatewayStatusCallback,
68                         true /* isMobileDataEnabled */,
69                         mDeps);
70 
71         vgc.setQuitting();
72         vgc.transitionTo(vgc.mDisconnectedState);
73         mTestLooper.dispatchAll();
74 
75         assertNull(vgc.getCurrentState());
76     }
77 
78     @Test
testNetworkChangesTriggerStateTransitions()79     public void testNetworkChangesTriggerStateTransitions() throws Exception {
80         mGatewayConnection
81                 .getUnderlyingNetworkControllerCallback()
82                 .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_1);
83         mTestLooper.dispatchAll();
84 
85         assertEquals(mGatewayConnection.mConnectingState, mGatewayConnection.getCurrentState());
86         verifySafeModeTimeoutAlarmAndGetCallback(false /* expectCanceled */);
87     }
88 
89     @Test
testNullNetworkDoesNotTriggerStateTransition()90     public void testNullNetworkDoesNotTriggerStateTransition() throws Exception {
91         mGatewayConnection
92                 .getUnderlyingNetworkControllerCallback()
93                 .onSelectedUnderlyingNetworkChanged(null);
94         mTestLooper.dispatchAll();
95 
96         assertEquals(mGatewayConnection.mDisconnectedState, mGatewayConnection.getCurrentState());
97         verifyDisconnectRequestAlarmAndGetCallback(false /* expectCanceled */);
98     }
99 
100     @Test
testTeardown()101     public void testTeardown() throws Exception {
102         mGatewayConnection.teardownAsynchronously();
103         mTestLooper.dispatchAll();
104 
105         // Verify that sending a non-quitting disconnect request does not unset the isQuitting flag
106         mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false);
107         mTestLooper.dispatchAll();
108 
109         assertNull(mGatewayConnection.getCurrentState());
110         verify(mIpSecSvc).deleteTunnelInterface(eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), any());
111         verifySafeModeTimeoutAlarmAndGetCallback(true /* expectCanceled */);
112         assertTrue(mGatewayConnection.isQuitting());
113         verify(mGatewayStatusCallback).onQuit();
114     }
115 
116     @Test
testNonTeardownDisconnectRequest()117     public void testNonTeardownDisconnectRequest() throws Exception {
118         mGatewayConnection.sendDisconnectRequestedAndAcquireWakelock("TEST", false);
119         mTestLooper.dispatchAll();
120 
121         assertEquals(mGatewayConnection.mDisconnectedState, mGatewayConnection.getCurrentState());
122         assertFalse(mGatewayConnection.isQuitting());
123         verify(mGatewayStatusCallback, never()).onQuit();
124         // No safe mode timer changes expected.
125     }
126 }
127