diff --git a/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/ChildSessionParamsTest.java b/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/ChildSessionParamsTest.java index 316355252a..7fb1b6dc43 100644 --- a/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/ChildSessionParamsTest.java +++ b/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/ChildSessionParamsTest.java @@ -16,20 +16,36 @@ package android.net.ipsec.ike.cts; +import static android.system.OsConstants.AF_INET; +import static android.system.OsConstants.AF_INET6; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import android.net.LinkAddress; import android.net.ipsec.ike.ChildSaProposal; import android.net.ipsec.ike.ChildSessionParams; import android.net.ipsec.ike.TransportModeChildSessionParams; import android.net.ipsec.ike.TunnelModeChildSessionParams; +import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv4Address; +import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv4DhcpServer; +import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv4DnsServer; +import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv4Netmask; +import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv6Address; +import android.net.ipsec.ike.TunnelModeChildSessionParams.ConfigRequestIpv6DnsServer; +import android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest; import androidx.test.ext.junit.runners.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +import java.net.Inet4Address; import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; @RunWith(AndroidJUnit4.class) @@ -137,4 +153,78 @@ public class ChildSessionParamsTest extends IkeTestBase { verifyTunnelModeChildParamsWithCustomizedValues(childParams); } + + @Test + public void testBuildChildSessionParamsWithConfigReq() { + TunnelModeChildSessionParams childParams = + new TunnelModeChildSessionParams.Builder() + .addSaProposal(mSaProposal) + .addInternalAddressRequest(AF_INET) + .addInternalAddressRequest(AF_INET6) + .addInternalAddressRequest(AF_INET6) + .addInternalAddressRequest(IPV4_ADDRESS_REMOTE) + .addInternalAddressRequest(IPV6_ADDRESS_REMOTE, IP6_PREFIX_LEN) + .addInternalDnsServerRequest(AF_INET) + .addInternalDnsServerRequest(AF_INET6) + .addInternalDhcpServerRequest(AF_INET) + .addInternalDhcpServerRequest(AF_INET) + .build(); + + verifyTunnelModeChildParamsWithDefaultValues(childParams); + + // Verify config request types and number of requests for each type + Map, Integer> expectedAttributeCounts = + new HashMap<>(); + expectedAttributeCounts.put(ConfigRequestIpv4Address.class, 2); + expectedAttributeCounts.put(ConfigRequestIpv6Address.class, 3); + expectedAttributeCounts.put(ConfigRequestIpv4Netmask.class, 1); + expectedAttributeCounts.put(ConfigRequestIpv4DnsServer.class, 1); + expectedAttributeCounts.put(ConfigRequestIpv6DnsServer.class, 1); + expectedAttributeCounts.put(ConfigRequestIpv4DhcpServer.class, 2); + verifyConfigRequestTypes(expectedAttributeCounts, childParams.getConfigurationRequests()); + + // Verify specific IPv4 address request + Set expectedV4Addresses = new HashSet<>(); + expectedV4Addresses.add(IPV4_ADDRESS_REMOTE); + verifySpecificV4AddrConfigReq(expectedV4Addresses, childParams); + + // Verify specific IPv6 address request + Set expectedV6Addresses = new HashSet<>(); + expectedV6Addresses.add(new LinkAddress(IPV6_ADDRESS_REMOTE, IP6_PREFIX_LEN)); + verifySpecificV6AddrConfigReq(expectedV6Addresses, childParams); + } + + protected void verifySpecificV4AddrConfigReq( + Set expectedAddresses, TunnelModeChildSessionParams childParams) { + for (TunnelModeChildConfigRequest req : childParams.getConfigurationRequests()) { + if (req instanceof ConfigRequestIpv4Address + && ((ConfigRequestIpv4Address) req).getAddress() != null) { + Inet4Address address = ((ConfigRequestIpv4Address) req).getAddress(); + + // Fail if expectedAddresses does not contain this address + assertTrue(expectedAddresses.remove(address)); + } + } + + // Fail if any expected address is not found in result + assertTrue(expectedAddresses.isEmpty()); + } + + protected void verifySpecificV6AddrConfigReq( + Set expectedAddresses, TunnelModeChildSessionParams childParams) { + for (TunnelModeChildConfigRequest req : childParams.getConfigurationRequests()) { + if (req instanceof ConfigRequestIpv6Address + && ((ConfigRequestIpv6Address) req).getAddress() != null) { + ConfigRequestIpv6Address ipv6AddrReq = (ConfigRequestIpv6Address) req; + + // Fail if expectedAddresses does not contain this address + LinkAddress address = + new LinkAddress(ipv6AddrReq.getAddress(), ipv6AddrReq.getPrefixLength()); + assertTrue(expectedAddresses.remove(address)); + } + } + + // Fail if any expected address is not found in result + assertTrue(expectedAddresses.isEmpty()); + } } diff --git a/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeTestBase.java b/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeTestBase.java index d4b431e837..d3aa8d03d5 100644 --- a/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeTestBase.java +++ b/tests/cts/net/ipsec/src/android/net/ipsec/ike/cts/IkeTestBase.java @@ -16,11 +16,17 @@ package android.net.ipsec.ike.cts; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + import android.net.InetAddresses; import android.net.ipsec.ike.IkeTrafficSelector; import java.net.Inet4Address; import java.net.Inet6Address; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** Shared parameters and util methods for testing different components of IKE */ abstract class IkeTestBase { @@ -80,4 +86,35 @@ abstract class IkeTestBase { OUTBOUND_TS_END_PORT, InetAddresses.parseNumericAddress("2001:db8:255::64"), InetAddresses.parseNumericAddress("2001:db8:255::255")); + + // Verify Config requests in TunnelModeChildSessionParams and IkeSessionParams + void verifyConfigRequestTypes( + Map, Integer> expectedReqCntMap, List resultReqList) { + Map, Integer> resultReqCntMap = new HashMap<>(); + + // Verify that every config request type in resultReqList is expected, and build + // resultReqCntMap at the same time + for (T resultReq : resultReqList) { + boolean isResultReqExpected = false; + + for (Class expectedReqInterface : expectedReqCntMap.keySet()) { + if (expectedReqInterface.isInstance(resultReq)) { + isResultReqExpected = true; + + resultReqCntMap.put( + expectedReqInterface, + resultReqCntMap.getOrDefault(expectedReqInterface, 0) + 1); + } + } + + if (!isResultReqExpected) { + fail("Failed due to unexpected config request " + resultReq); + } + } + + assertEquals(expectedReqCntMap, resultReqCntMap); + + // TODO: Think of a neat way to validate both counts and values in this method. Probably can + // build Runnables as validators for count and values. + } }