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 android.net.vcn; 18 19 import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE; 20 import static android.net.vcn.VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES; 21 import static android.net.vcn.VcnGatewayConnectionConfig.UNDERLYING_NETWORK_TEMPLATES_KEY; 22 import static android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY; 23 24 import static org.junit.Assert.assertArrayEquals; 25 import static org.junit.Assert.assertEquals; 26 import static org.junit.Assert.assertFalse; 27 import static org.junit.Assert.assertNotEquals; 28 import static org.junit.Assert.assertNotSame; 29 import static org.junit.Assert.assertTrue; 30 import static org.junit.Assert.fail; 31 32 import android.net.NetworkCapabilities; 33 import android.net.ipsec.ike.IkeSessionParams; 34 import android.net.ipsec.ike.IkeTunnelConnectionParams; 35 import android.net.vcn.persistablebundleutils.IkeSessionParamsUtilsTest; 36 import android.net.vcn.persistablebundleutils.TunnelConnectionParamsUtilsTest; 37 import android.os.PersistableBundle; 38 39 import androidx.test.filters.SmallTest; 40 import androidx.test.runner.AndroidJUnit4; 41 42 import org.junit.Test; 43 import org.junit.runner.RunWith; 44 45 import java.util.ArrayList; 46 import java.util.Arrays; 47 import java.util.Collections; 48 import java.util.List; 49 import java.util.Set; 50 import java.util.concurrent.TimeUnit; 51 52 @RunWith(AndroidJUnit4.class) 53 @SmallTest 54 public class VcnGatewayConnectionConfigTest { 55 // Public for use in VcnGatewayConnectionTest 56 public static final int[] EXPOSED_CAPS = 57 new int[] { 58 NetworkCapabilities.NET_CAPABILITY_INTERNET, NetworkCapabilities.NET_CAPABILITY_MMS 59 }; 60 public static final int[] UNDERLYING_CAPS = new int[] {NetworkCapabilities.NET_CAPABILITY_DUN}; 61 62 private static final List<VcnUnderlyingNetworkTemplate> UNDERLYING_NETWORK_TEMPLATES = 63 new ArrayList(); 64 65 static { 66 Arrays.sort(EXPOSED_CAPS); 67 Arrays.sort(UNDERLYING_CAPS); 68 69 UNDERLYING_NETWORK_TEMPLATES.add( VcnCellUnderlyingNetworkTemplateTest.getTestNetworkTemplate()70 VcnCellUnderlyingNetworkTemplateTest.getTestNetworkTemplate()); 71 UNDERLYING_NETWORK_TEMPLATES.add( VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkTemplate()72 VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkTemplate()); 73 } 74 75 public static final long[] RETRY_INTERVALS_MS = 76 new long[] { 77 TimeUnit.SECONDS.toMillis(5), 78 TimeUnit.SECONDS.toMillis(30), 79 TimeUnit.MINUTES.toMillis(1), 80 TimeUnit.MINUTES.toMillis(5), 81 TimeUnit.MINUTES.toMillis(15), 82 TimeUnit.MINUTES.toMillis(30) 83 }; 84 public static final int MAX_MTU = 1360; 85 public static final int MIN_UDP_PORT_4500_NAT_TIMEOUT = 120; 86 87 private static final Set<Integer> GATEWAY_OPTIONS = 88 Collections.singleton(VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY); 89 90 public static final IkeTunnelConnectionParams TUNNEL_CONNECTION_PARAMS = 91 TunnelConnectionParamsUtilsTest.buildTestParams(); 92 93 public static final String GATEWAY_CONNECTION_NAME_PREFIX = "gatewayConnectionName-"; 94 private static int sGatewayConnectionConfigCount = 0; 95 buildTestConfig( String gatewayConnectionName, IkeTunnelConnectionParams tunnelConnectionParams)96 private static VcnGatewayConnectionConfig buildTestConfig( 97 String gatewayConnectionName, IkeTunnelConnectionParams tunnelConnectionParams) { 98 return buildTestConfigWithExposedCaps( 99 new VcnGatewayConnectionConfig.Builder( 100 gatewayConnectionName, tunnelConnectionParams), 101 EXPOSED_CAPS); 102 } 103 104 // Public for use in UnderlyingNetworkControllerTest buildTestConfig( List<VcnUnderlyingNetworkTemplate> nwTemplates)105 public static VcnGatewayConnectionConfig buildTestConfig( 106 List<VcnUnderlyingNetworkTemplate> nwTemplates) { 107 final VcnGatewayConnectionConfig.Builder builder = 108 newBuilder() 109 .setVcnUnderlyingNetworkPriorities(nwTemplates) 110 .setMinUdpPort4500NatTimeoutSeconds(MIN_UDP_PORT_4500_NAT_TIMEOUT); 111 112 return buildTestConfigWithExposedCaps(builder, EXPOSED_CAPS); 113 } 114 115 // Public for use in VcnGatewayConnectionTest buildTestConfig()116 public static VcnGatewayConnectionConfig buildTestConfig() { 117 return buildTestConfig(UNDERLYING_NETWORK_TEMPLATES); 118 } 119 newBuilder()120 private static VcnGatewayConnectionConfig.Builder newBuilder() { 121 // Append a unique identifier to the name prefix to guarantee that all created 122 // VcnGatewayConnectionConfigs have a unique name (required by VcnConfig). 123 return new VcnGatewayConnectionConfig.Builder( 124 GATEWAY_CONNECTION_NAME_PREFIX + sGatewayConnectionConfigCount++, 125 TUNNEL_CONNECTION_PARAMS); 126 } 127 buildTestConfigWithExposedCapsAndOptions( VcnGatewayConnectionConfig.Builder builder, Set<Integer> gatewayOptions, int... exposedCaps)128 private static VcnGatewayConnectionConfig buildTestConfigWithExposedCapsAndOptions( 129 VcnGatewayConnectionConfig.Builder builder, 130 Set<Integer> gatewayOptions, 131 int... exposedCaps) { 132 builder.setRetryIntervalsMillis(RETRY_INTERVALS_MS).setMaxMtu(MAX_MTU); 133 134 for (int option : gatewayOptions) { 135 builder.addGatewayOption(option); 136 } 137 138 for (int caps : exposedCaps) { 139 builder.addExposedCapability(caps); 140 } 141 142 return builder.build(); 143 } 144 buildTestConfigWithExposedCaps( VcnGatewayConnectionConfig.Builder builder, int... exposedCaps)145 private static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps( 146 VcnGatewayConnectionConfig.Builder builder, int... exposedCaps) { 147 return buildTestConfigWithExposedCapsAndOptions( 148 builder, Collections.emptySet(), exposedCaps); 149 } 150 151 // Public for use in VcnGatewayConnectionTest buildTestConfigWithExposedCaps(int... exposedCaps)152 public static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(int... exposedCaps) { 153 return buildTestConfigWithExposedCaps(newBuilder(), exposedCaps); 154 } 155 buildTestConfigWithGatewayOptions( VcnGatewayConnectionConfig.Builder builder, Set<Integer> gatewayOptions)156 private static VcnGatewayConnectionConfig buildTestConfigWithGatewayOptions( 157 VcnGatewayConnectionConfig.Builder builder, Set<Integer> gatewayOptions) { 158 return buildTestConfigWithExposedCapsAndOptions(builder, gatewayOptions, EXPOSED_CAPS); 159 } 160 161 // Public for use in VcnGatewayConnectionTest buildTestConfigWithGatewayOptions( Set<Integer> gatewayOptions)162 public static VcnGatewayConnectionConfig buildTestConfigWithGatewayOptions( 163 Set<Integer> gatewayOptions) { 164 return buildTestConfigWithExposedCapsAndOptions(newBuilder(), gatewayOptions, EXPOSED_CAPS); 165 } 166 167 @Test testBuilderRequiresNonNullGatewayConnectionName()168 public void testBuilderRequiresNonNullGatewayConnectionName() { 169 try { 170 new VcnGatewayConnectionConfig.Builder( 171 null /* gatewayConnectionName */, TUNNEL_CONNECTION_PARAMS) 172 .build(); 173 174 fail("Expected exception due to invalid gateway connection name"); 175 } catch (NullPointerException e) { 176 } 177 } 178 179 @Test testBuilderRequiresNonNullTunnelConnectionParams()180 public void testBuilderRequiresNonNullTunnelConnectionParams() { 181 try { 182 new VcnGatewayConnectionConfig.Builder( 183 GATEWAY_CONNECTION_NAME_PREFIX, null /* tunnelConnectionParams */) 184 .build(); 185 186 fail("Expected exception due to the absence of tunnel connection parameters"); 187 } catch (NullPointerException e) { 188 } 189 } 190 191 @Test testBuilderRequiresMobikeEnabled()192 public void testBuilderRequiresMobikeEnabled() { 193 try { 194 final IkeSessionParams ikeParams = 195 IkeSessionParamsUtilsTest.createBuilderMinimum() 196 .removeIkeOption(IKE_OPTION_MOBIKE) 197 .build(); 198 final IkeTunnelConnectionParams tunnelParams = 199 TunnelConnectionParamsUtilsTest.buildTestParams(ikeParams); 200 new VcnGatewayConnectionConfig.Builder(GATEWAY_CONNECTION_NAME_PREFIX, tunnelParams); 201 fail("Expected exception due to MOBIKE not enabled"); 202 } catch (IllegalArgumentException e) { 203 } 204 } 205 206 @Test testBuilderRequiresNonEmptyExposedCaps()207 public void testBuilderRequiresNonEmptyExposedCaps() { 208 try { 209 newBuilder().build(); 210 211 fail("Expected exception due to invalid exposed capabilities"); 212 } catch (IllegalArgumentException e) { 213 } 214 } 215 216 @Test testBuilderRequiresNonNullNetworkTemplates()217 public void testBuilderRequiresNonNullNetworkTemplates() { 218 try { 219 newBuilder().setVcnUnderlyingNetworkPriorities(null); 220 fail("Expected exception due to invalid underlyingNetworkTemplates"); 221 } catch (NullPointerException e) { 222 } 223 } 224 225 @Test testBuilderRequiresNonNullRetryInterval()226 public void testBuilderRequiresNonNullRetryInterval() { 227 try { 228 newBuilder().setRetryIntervalsMillis(null); 229 fail("Expected exception due to invalid retryIntervalMs"); 230 } catch (IllegalArgumentException e) { 231 } 232 } 233 234 @Test testBuilderRequiresNonEmptyRetryInterval()235 public void testBuilderRequiresNonEmptyRetryInterval() { 236 try { 237 newBuilder().setRetryIntervalsMillis(new long[0]); 238 fail("Expected exception due to invalid retryIntervalMs"); 239 } catch (IllegalArgumentException e) { 240 } 241 } 242 243 @Test testBuilderRequiresValidMtu()244 public void testBuilderRequiresValidMtu() { 245 try { 246 newBuilder().setMaxMtu(VcnGatewayConnectionConfig.MIN_MTU_V6 - 1); 247 fail("Expected exception due to invalid mtu"); 248 } catch (IllegalArgumentException e) { 249 } 250 } 251 252 @Test testBuilderRequiresValidOption()253 public void testBuilderRequiresValidOption() { 254 try { 255 newBuilder().addGatewayOption(-1); 256 fail("Expected exception due to the invalid VCN gateway option"); 257 } catch (IllegalArgumentException e) { 258 } 259 } 260 261 @Test testBuilderAndGetters()262 public void testBuilderAndGetters() { 263 final VcnGatewayConnectionConfig config = buildTestConfig(); 264 265 assertTrue(config.getGatewayConnectionName().startsWith(GATEWAY_CONNECTION_NAME_PREFIX)); 266 267 int[] exposedCaps = config.getExposedCapabilities(); 268 Arrays.sort(exposedCaps); 269 assertArrayEquals(EXPOSED_CAPS, exposedCaps); 270 271 assertEquals(UNDERLYING_NETWORK_TEMPLATES, config.getVcnUnderlyingNetworkPriorities()); 272 assertEquals(TUNNEL_CONNECTION_PARAMS, config.getTunnelConnectionParams()); 273 274 assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMillis()); 275 assertEquals(MAX_MTU, config.getMaxMtu()); 276 277 assertFalse( 278 config.hasGatewayOption( 279 VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY)); 280 } 281 282 @Test testBuilderAndGettersWithOptions()283 public void testBuilderAndGettersWithOptions() { 284 final VcnGatewayConnectionConfig config = 285 buildTestConfigWithGatewayOptions(GATEWAY_OPTIONS); 286 287 for (int option : GATEWAY_OPTIONS) { 288 assertTrue(config.hasGatewayOption(option)); 289 } 290 } 291 292 @Test testPersistableBundle()293 public void testPersistableBundle() { 294 final VcnGatewayConnectionConfig config = buildTestConfig(); 295 296 assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle())); 297 } 298 299 @Test testPersistableBundleWithOptions()300 public void testPersistableBundleWithOptions() { 301 final VcnGatewayConnectionConfig config = 302 buildTestConfigWithGatewayOptions(GATEWAY_OPTIONS); 303 304 assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle())); 305 } 306 307 @Test testParsePersistableBundleWithoutVcnUnderlyingNetworkTemplates()308 public void testParsePersistableBundleWithoutVcnUnderlyingNetworkTemplates() { 309 PersistableBundle configBundle = buildTestConfig().toPersistableBundle(); 310 configBundle.putPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY, null); 311 312 final VcnGatewayConnectionConfig config = new VcnGatewayConnectionConfig(configBundle); 313 assertEquals( 314 DEFAULT_UNDERLYING_NETWORK_TEMPLATES, config.getVcnUnderlyingNetworkPriorities()); 315 } 316 buildTunnelConnectionParams(String ikePsk)317 private static IkeTunnelConnectionParams buildTunnelConnectionParams(String ikePsk) { 318 final IkeSessionParams ikeParams = 319 IkeSessionParamsUtilsTest.createBuilderMinimum() 320 .setAuthPsk(ikePsk.getBytes()) 321 .build(); 322 return TunnelConnectionParamsUtilsTest.buildTestParams(ikeParams); 323 } 324 325 @Test testTunnelConnectionParamsEquals()326 public void testTunnelConnectionParamsEquals() throws Exception { 327 final String connectionName = "testTunnelConnectionParamsEquals.connectionName"; 328 final String psk = "testTunnelConnectionParamsEquals.psk"; 329 330 final IkeTunnelConnectionParams tunnelParams = buildTunnelConnectionParams(psk); 331 final VcnGatewayConnectionConfig config = buildTestConfig(connectionName, tunnelParams); 332 333 final IkeTunnelConnectionParams anotherTunnelParams = buildTunnelConnectionParams(psk); 334 final VcnGatewayConnectionConfig anotherConfig = 335 buildTestConfig(connectionName, anotherTunnelParams); 336 337 assertNotSame(tunnelParams, anotherTunnelParams); 338 assertEquals(tunnelParams, anotherTunnelParams); 339 assertEquals(config, anotherConfig); 340 } 341 342 @Test testTunnelConnectionParamsNotEquals()343 public void testTunnelConnectionParamsNotEquals() throws Exception { 344 final String connectionName = "testTunnelConnectionParamsNotEquals.connectionName"; 345 346 final IkeTunnelConnectionParams tunnelParams = 347 buildTunnelConnectionParams("testTunnelConnectionParamsNotEquals.pskA"); 348 final VcnGatewayConnectionConfig config = buildTestConfig(connectionName, tunnelParams); 349 350 final IkeTunnelConnectionParams anotherTunnelParams = 351 buildTunnelConnectionParams("testTunnelConnectionParamsNotEquals.pskB"); 352 final VcnGatewayConnectionConfig anotherConfig = 353 buildTestConfig(connectionName, anotherTunnelParams); 354 355 assertNotEquals(tunnelParams, anotherTunnelParams); 356 assertNotEquals(config, anotherConfig); 357 } 358 buildTestConfigWithVcnUnderlyingNetworkTemplates( List<VcnUnderlyingNetworkTemplate> networkTemplates)359 private static VcnGatewayConnectionConfig buildTestConfigWithVcnUnderlyingNetworkTemplates( 360 List<VcnUnderlyingNetworkTemplate> networkTemplates) { 361 return buildTestConfigWithExposedCaps( 362 new VcnGatewayConnectionConfig.Builder( 363 "buildTestConfigWithVcnUnderlyingNetworkTemplates", 364 TUNNEL_CONNECTION_PARAMS) 365 .setVcnUnderlyingNetworkPriorities(networkTemplates), 366 EXPOSED_CAPS); 367 } 368 369 @Test testVcnUnderlyingNetworkTemplatesEquality()370 public void testVcnUnderlyingNetworkTemplatesEquality() throws Exception { 371 final VcnGatewayConnectionConfig config = 372 buildTestConfigWithVcnUnderlyingNetworkTemplates(UNDERLYING_NETWORK_TEMPLATES); 373 374 final List<VcnUnderlyingNetworkTemplate> networkTemplatesEqual = new ArrayList(); 375 networkTemplatesEqual.add(VcnCellUnderlyingNetworkTemplateTest.getTestNetworkTemplate()); 376 networkTemplatesEqual.add(VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkTemplate()); 377 final VcnGatewayConnectionConfig configEqual = 378 buildTestConfigWithVcnUnderlyingNetworkTemplates(networkTemplatesEqual); 379 380 final List<VcnUnderlyingNetworkTemplate> networkTemplatesNotEqual = new ArrayList(); 381 networkTemplatesNotEqual.add(VcnWifiUnderlyingNetworkTemplateTest.getTestNetworkTemplate()); 382 final VcnGatewayConnectionConfig configNotEqual = 383 buildTestConfigWithVcnUnderlyingNetworkTemplates(networkTemplatesNotEqual); 384 385 assertEquals(UNDERLYING_NETWORK_TEMPLATES, networkTemplatesEqual); 386 assertEquals(config, configEqual); 387 388 assertNotEquals(UNDERLYING_NETWORK_TEMPLATES, networkTemplatesNotEqual); 389 assertNotEquals(config, configNotEqual); 390 } 391 buildConfigWithGatewayOptionsForEqualityTest( Set<Integer> gatewayOptions)392 private static VcnGatewayConnectionConfig buildConfigWithGatewayOptionsForEqualityTest( 393 Set<Integer> gatewayOptions) { 394 return buildTestConfigWithGatewayOptions( 395 new VcnGatewayConnectionConfig.Builder( 396 "buildConfigWithGatewayOptionsForEqualityTest", TUNNEL_CONNECTION_PARAMS), 397 gatewayOptions); 398 } 399 400 @Test testVcnGatewayOptionsEquality()401 public void testVcnGatewayOptionsEquality() throws Exception { 402 final VcnGatewayConnectionConfig config = 403 buildConfigWithGatewayOptionsForEqualityTest(GATEWAY_OPTIONS); 404 405 final VcnGatewayConnectionConfig configEqual = 406 buildConfigWithGatewayOptionsForEqualityTest(GATEWAY_OPTIONS); 407 408 final VcnGatewayConnectionConfig configNotEqual = 409 buildConfigWithGatewayOptionsForEqualityTest(Collections.emptySet()); 410 411 assertEquals(config, configEqual); 412 assertNotEquals(config, configNotEqual); 413 } 414 } 415