diff options
6 files changed, 95 insertions, 49 deletions
diff --git a/tests/integration/src/android/net/ip/IpClientIntegrationTest.java b/tests/integration/src/android/net/ip/IpClientIntegrationTest.java index 334ac00..902d5ee 100644 --- a/tests/integration/src/android/net/ip/IpClientIntegrationTest.java +++ b/tests/integration/src/android/net/ip/IpClientIntegrationTest.java @@ -132,12 +132,14 @@ import com.android.networkstack.arp.ArpPacket; import com.android.server.NetworkObserverRegistry; import com.android.server.NetworkStackService.NetworkStackServiceManager; import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService; +import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import com.android.testutils.HandlerUtilsKt; import com.android.testutils.TapPacketReader; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -174,6 +176,9 @@ public class IpClientIntegrationTest { private static final String TEST_GROUPHINT = "some grouphint"; private static final int TEST_LEASE_DURATION_S = 3_600; // 1 hour + @Rule + public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); + @Mock private Context mContext; @Mock private ConnectivityManager mCm; @Mock private Resources mResources; @@ -1650,11 +1655,17 @@ public class IpClientIntegrationTest { final Uri expectedUrl = featureEnabled && serverSendsOption ? Uri.parse(TEST_CAPTIVE_PORTAL_URL) : null; - // Wait for LinkProperties containing DHCP-obtained info, such as MTU, and ensure that the - // URL is set as expected - verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange(argThat(lp -> - lp.getMtu() == testMtu - && Objects.equals(expectedUrl, lp.getCaptivePortalApiUrl()))); + // Wait for LinkProperties containing DHCP-obtained info, such as MTU + final ArgumentCaptor<LinkProperties> captor = ArgumentCaptor.forClass(LinkProperties.class); + verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange( + argThat(lp -> lp.getMtu() == testMtu)); + + // Ensure that the URL was set as expected in the callbacks. + // Can't verify the URL up to Q as there is no such attribute in LinkProperties. + if (!ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)) return; + verify(mCb).onLinkPropertiesChange(captor.capture()); + assertTrue(captor.getAllValues().stream().anyMatch( + lp -> Objects.equals(expectedUrl, lp.getCaptivePortalApiUrl()))); } @Test diff --git a/tests/unit/src/android/net/netlink/StructNdOptPref64Test.java b/tests/unit/src/android/net/netlink/StructNdOptPref64Test.java index fef103b..a09805e 100644 --- a/tests/unit/src/android/net/netlink/StructNdOptPref64Test.java +++ b/tests/unit/src/android/net/netlink/StructNdOptPref64Test.java @@ -64,7 +64,7 @@ public class StructNdOptPref64Test { } private void assertToByteBufferMatches(StructNdOptPref64 opt, String expected) { - String actual = HexEncoding.encodeToString(opt.toByteBuffer().array(), false /*upperCase*/); + String actual = HexEncoding.encodeToString(opt.toByteBuffer().array()); assertEquals(expected, actual); } @@ -85,18 +85,18 @@ public class StructNdOptPref64Test { public void testParseCannedOption() throws Exception { String hexBytes = "2602" // type=38, len=2 (16 bytes) + "0088" // lifetime=136, PLC=0 (/96) - + "20010db80003000400050006"; // 2001:db8:3:4:5:6/96 + + "20010DB80003000400050006"; // 2001:db8:3:4:5:6/96 byte[] rawBytes = HexEncoding.decode(hexBytes); StructNdOptPref64 opt = StructNdOptPref64.parse(ByteBuffer.wrap(rawBytes)); - assertPref64OptMatches(136, prefix("2001:db8:3:4:5:6::", 96), opt); + assertPref64OptMatches(136, prefix("2001:DB8:3:4:5:6::", 96), opt); assertToByteBufferMatches(opt, hexBytes); hexBytes = "2602" // type=38, len=2 (16 bytes) + "2752" // lifetime=10064, PLC=2 (/56) - + "0064ff9b0000000000000000"; // 64:ff9b::/56 + + "0064FF9B0000000000000000"; // 64:ff9b::/56 rawBytes = HexEncoding.decode(hexBytes); opt = StructNdOptPref64.parse(ByteBuffer.wrap(rawBytes)); - assertPref64OptMatches(10064, prefix("64:ff9b::", 56), opt); + assertPref64OptMatches(10064, prefix("64:FF9B::", 56), opt); assertToByteBufferMatches(opt, hexBytes); } @@ -185,12 +185,12 @@ public class StructNdOptPref64Test { final IpPrefix prefix2 = prefix(PREFIX2, 96); StructNdOptPref64 opt = new StructNdOptPref64(prefix1, 600); - assertToByteBufferMatches(opt, "2602025a0064ff9b0000000000000000"); + assertToByteBufferMatches(opt, "2602025A0064FF9B0000000000000000"); assertEquals(new IpPrefix("64:ff9b::/56"), opt.prefix); assertEquals(600, opt.lifetime); opt = new StructNdOptPref64(prefix2, 65519); - assertToByteBufferMatches(opt, "2602ffe820010db80001000200030064"); + assertToByteBufferMatches(opt, "2602FFE820010DB80001000200030064"); assertEquals(new IpPrefix("2001:db8:1:2:3:64::/96"), opt.prefix); assertEquals(65512, opt.lifetime); diff --git a/tests/unit/src/android/net/networkstack/ModuleNetworkStackClientTest.kt b/tests/unit/src/android/net/networkstack/ModuleNetworkStackClientTest.kt index 77ee15e..2d6a095 100644 --- a/tests/unit/src/android/net/networkstack/ModuleNetworkStackClientTest.kt +++ b/tests/unit/src/android/net/networkstack/ModuleNetworkStackClientTest.kt @@ -29,10 +29,10 @@ import android.os.Build import android.os.IBinder import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import com.android.networkstack.apishim.ShimUtils +import com.android.testutils.DevSdkIgnoreRule import org.junit.After -import org.junit.Assume.assumeTrue import org.junit.Before +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any @@ -50,6 +50,10 @@ class ModuleNetworkStackClientTest { private val TEST_NETWORK = Network(43) private val TEST_TIMEOUT_MS = 500L + // ModuleNetworkStackClient is only available after Q + @Rule @JvmField + val mIgnoreRule = DevSdkIgnoreRule(ignoreClassUpTo = Build.VERSION_CODES.Q) + @Mock private lateinit var mContext: Context @Mock @@ -67,8 +71,6 @@ class ModuleNetworkStackClientTest { @Before fun setUp() { - // ModuleNetworkStackClient is only available after Q - assumeTrue(ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.Q)) MockitoAnnotations.initMocks(this) doReturn(mConnector).`when`(mConnectorBinder).queryLocalInterface( INetworkStackConnector::class.qualifiedName!!) diff --git a/tests/unit/src/android/net/testutils/NetworkStatsUtilsTest.kt b/tests/unit/src/android/net/testutils/NetworkStatsUtilsTest.kt index 08788e0..7e4ae0b 100644 --- a/tests/unit/src/android/net/testutils/NetworkStatsUtilsTest.kt +++ b/tests/unit/src/android/net/testutils/NetworkStatsUtilsTest.kt @@ -19,7 +19,10 @@ package android.net.testutils import android.net.NetworkStats import android.net.NetworkStats.SET_DEFAULT import android.net.NetworkStats.TAG_NONE +import android.os.Build +import com.android.testutils.DevSdkIgnoreRule import com.android.testutils.orderInsensitiveEquals +import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -32,6 +35,10 @@ private const val TEST_START = 1194220800000L @RunWith(JUnit4::class) class NetworkStatsUtilsTest { + // This is a unit test for a test utility that uses R APIs + @Rule @JvmField + val ignoreRule = DevSdkIgnoreRule(ignoreClassUpTo = Build.VERSION_CODES.Q) + @Test fun testOrderInsensitiveEquals() { val testEntry = arrayOf( diff --git a/tests/unit/src/com/android/networkstack/NetworkStackNotifierTest.kt b/tests/unit/src/com/android/networkstack/NetworkStackNotifierTest.kt index 9100c91..1be6ee7 100644 --- a/tests/unit/src/com/android/networkstack/NetworkStackNotifierTest.kt +++ b/tests/unit/src/com/android/networkstack/NetworkStackNotifierTest.kt @@ -98,6 +98,16 @@ class NetworkStackNotifierTest { private lateinit var mAllNetworksCb: NetworkCallback private lateinit var mDefaultNetworkCb: NetworkCallback + // Lazy-init as CaptivePortalData does not exist on Q. + private val mTestCapportLp by lazy { + LinkProperties().apply { + captivePortalData = CaptivePortalData.Builder() + .setCaptive(false) + .setVenueInfoUrl(Uri.parse(TEST_VENUE_INFO_URL)) + .build() + } + } + private val TEST_NETWORK = Network(42) private val TEST_NETWORK_TAG = TEST_NETWORK.networkHandle.toString() private val TEST_SSID = "TestSsid" @@ -111,12 +121,6 @@ class NetworkStackNotifierTest { private val TEST_VENUE_INFO_URL = "https://testvenue.example.com/info" private val EMPTY_CAPPORT_LP = LinkProperties() - private val TEST_CAPPORT_LP = LinkProperties().apply { - captivePortalData = CaptivePortalData.Builder() - .setCaptive(false) - .setVenueInfoUrl(Uri.parse(TEST_VENUE_INFO_URL)) - .build() - } @Before fun setUp() { @@ -226,7 +230,7 @@ class NetworkStackNotifierTest { // Venue info (CaptivePortalData) is not available for API <= Q assumeTrue(NetworkInformationShimImpl.useApiAboveQ()) mNotifier.notifyCaptivePortalValidationPending(TEST_NETWORK) - onLinkPropertiesChanged(TEST_CAPPORT_LP) + onLinkPropertiesChanged(mTestCapportLp) onDefaultNetworkAvailable(TEST_NETWORK) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES).setSSID(TEST_SSID) onCapabilitiesChanged(capabilities) @@ -245,7 +249,7 @@ class NetworkStackNotifierTest { assumeTrue(NetworkInformationShimImpl.useApiAboveQ()) doReturn(null).`when`(mNm).getNotificationChannel(CHANNEL_VENUE_INFO) mNotifier.notifyCaptivePortalValidationPending(TEST_NETWORK) - onLinkPropertiesChanged(TEST_CAPPORT_LP) + onLinkPropertiesChanged(mTestCapportLp) onDefaultNetworkAvailable(TEST_NETWORK) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES).setSSID(TEST_SSID) onCapabilitiesChanged(capabilities) @@ -261,7 +265,7 @@ class NetworkStackNotifierTest { fun testVenueInfoNotification() { // Venue info (CaptivePortalData) is not available for API <= Q assumeTrue(NetworkInformationShimImpl.useApiAboveQ()) - onLinkPropertiesChanged(TEST_CAPPORT_LP) + onLinkPropertiesChanged(mTestCapportLp) onDefaultNetworkAvailable(TEST_NETWORK) val capabilities = NetworkCapabilities(VALIDATED_CAPABILITIES).setSSID(TEST_SSID) onCapabilitiesChanged(capabilities) @@ -279,7 +283,7 @@ class NetworkStackNotifierTest { // Venue info (CaptivePortalData) is not available for API <= Q assumeTrue(NetworkInformationShimImpl.useApiAboveQ()) doReturn(null).`when`(mNm).getNotificationChannel(CHANNEL_VENUE_INFO) - onLinkPropertiesChanged(TEST_CAPPORT_LP) + onLinkPropertiesChanged(mTestCapportLp) onDefaultNetworkAvailable(TEST_NETWORK) onCapabilitiesChanged(VALIDATED_CAPABILITIES) mLooper.processAllMessages() @@ -291,7 +295,7 @@ class NetworkStackNotifierTest { fun testNonDefaultVenueInfoNotification() { // Venue info (CaptivePortalData) is not available for API <= Q assumeTrue(NetworkInformationShimImpl.useApiAboveQ()) - onLinkPropertiesChanged(TEST_CAPPORT_LP) + onLinkPropertiesChanged(mTestCapportLp) onCapabilitiesChanged(VALIDATED_CAPABILITIES) mLooper.processAllMessages() @@ -313,7 +317,7 @@ class NetworkStackNotifierTest { fun testUnvalidatedNetworkVenueInfoNotification() { // Venue info (CaptivePortalData) is not available for API <= Q assumeTrue(NetworkInformationShimImpl.useApiAboveQ()) - onLinkPropertiesChanged(TEST_CAPPORT_LP) + onLinkPropertiesChanged(mTestCapportLp) onCapabilitiesChanged(EMPTY_CAPABILITIES) mLooper.processAllMessages() diff --git a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java index 26630f8..cc5b40d 100644 --- a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java +++ b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java @@ -72,8 +72,10 @@ import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -111,6 +113,7 @@ import android.os.Build; import android.os.Bundle; import android.os.ConditionVariable; import android.os.Handler; +import android.os.IBinder; import android.os.Looper; import android.os.PersistableBundle; import android.os.Process; @@ -137,10 +140,13 @@ import com.android.networkstack.metrics.DataStallDetectionStats; import com.android.networkstack.metrics.DataStallStatsUtils; import com.android.networkstack.netlink.TcpSocketTracker; import com.android.server.NetworkStackService.NetworkStackServiceManager; +import com.android.testutils.DevSdkIgnoreRule; +import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import com.android.testutils.HandlerUtilsKt; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -180,6 +186,9 @@ public class NetworkMonitorTest { private static final String LOCATION_HEADER = "location"; private static final String CONTENT_TYPE_HEADER = "Content-Type"; + @Rule + public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); + private @Mock Context mContext; private @Mock Configuration mConfiguration; private @Mock Resources mResources; @@ -202,7 +211,10 @@ public class NetworkMonitorTest { private @Mock HttpURLConnection mCapportApiConnection; private @Mock Random mRandom; private @Mock NetworkMonitor.Dependencies mDependencies; - private @Mock INetworkMonitorCallbacks mCallbacks; + // Mockito can't create a mock of INetworkMonitorCallbacks on Q because it can't find + // CaptivePortalData on notifyCaptivePortalDataChanged. Use a spy on a mock IBinder instead. + private INetworkMonitorCallbacks mCallbacks = spy( + INetworkMonitorCallbacks.Stub.asInterface(mock(IBinder.class))); private @Spy Network mCleartextDnsNetwork = new Network(TEST_NETID); private @Mock Network mNetwork; private @Mock DataStallStatsUtils mDataStallStatsUtils; @@ -257,9 +269,10 @@ public class NetworkMonitorTest { private static final int HANDLER_TIMEOUT_MS = 1000; private static final LinkProperties TEST_LINK_PROPERTIES = new LinkProperties(); - private static final LinkProperties CAPPORT_LINK_PROPERTIES = makeCapportLinkProperties(); - private static LinkProperties makeCapportLinkProperties() { + // Cannot have a static member for the LinkProperties with captive portal API information, as + // the initializer would crash on Q (the members in LinkProperties were introduced in R). + private static LinkProperties makeCapportLPs() { final LinkProperties lp = new LinkProperties(TEST_LINK_PROPERTIES); lp.setCaptivePortalApiUrl(Uri.parse(TEST_CAPPORT_API_URL)); return lp; @@ -534,7 +547,7 @@ public class NetworkMonitorTest { private void resetCallbacks(int interfaceVersion) { reset(mCallbacks); try { - when(mCallbacks.getInterfaceVersion()).thenReturn(interfaceVersion); + doReturn(interfaceVersion).when(mCallbacks).getInterfaceVersion(); } catch (RemoteException e) { // Can't happen as mCallbacks is a mock fail("Error mocking getInterfaceVersion" + e); @@ -997,7 +1010,7 @@ public class NetworkMonitorTest { + "'bytes-remaining': " + bytesRemaining + "," + "'seconds-remaining': " + secondsRemaining + "}"); - runNetworkTest(CAPPORT_LINK_PROPERTIES, METERED_CAPABILITIES, VALIDATION_RESULT_PORTAL); + runNetworkTest(makeCapportLPs(), METERED_CAPABILITIES, VALIDATION_RESULT_PORTAL); verify(mHttpConnection, never()).getResponseCode(); verify(mCapportApiConnection).getResponseCode(); @@ -1024,11 +1037,13 @@ public class NetworkMonitorTest { setApiContent(mCapportApiConnection, "{'captive': true, " + "'user-portal-url': '" + TEST_LOGIN_URL + "'}"); - nm.notifyLinkPropertiesChanged(CAPPORT_LINK_PROPERTIES); + nm.notifyLinkPropertiesChanged(makeCapportLPs()); verifyNetworkTested(VALIDATION_RESULT_PORTAL); - verify(mCallbacks).notifyCaptivePortalDataChanged( - argThat(data -> Uri.parse(TEST_LOGIN_URL).equals(data.getUserPortalUrl()))); + final ArgumentCaptor<CaptivePortalData> capportCaptor = ArgumentCaptor.forClass( + CaptivePortalData.class); + verify(mCallbacks).notifyCaptivePortalDataChanged(capportCaptor.capture()); + assertEquals(Uri.parse(TEST_LOGIN_URL), capportCaptor.getValue().getUserPortalUrl()); assertEquals(TEST_LOGIN_URL, mNetworkTestedRedirectUrlCaptor.getValue()); // HTTP probe was sent on first validation but not re-sent when there was a portal URL. @@ -1043,10 +1058,12 @@ public class NetworkMonitorTest { setStatus(mHttpConnection, 500); setApiContent(mCapportApiConnection, "{'captive': false," + "'venue-info-url': '" + TEST_VENUE_INFO_URL + "'}"); - runNetworkTest(CAPPORT_LINK_PROPERTIES, METERED_CAPABILITIES, VALIDATION_RESULT_INVALID); + runNetworkTest(makeCapportLPs(), METERED_CAPABILITIES, VALIDATION_RESULT_INVALID); - verify(mCallbacks).notifyCaptivePortalDataChanged(argThat(data -> - Uri.parse(TEST_VENUE_INFO_URL).equals(data.getVenueInfoUrl()))); + final ArgumentCaptor<CaptivePortalData> capportCaptor = ArgumentCaptor.forClass( + CaptivePortalData.class); + verify(mCallbacks).notifyCaptivePortalDataChanged(capportCaptor.capture()); + assertEquals(Uri.parse(TEST_VENUE_INFO_URL), capportCaptor.getValue().getVenueInfoUrl()); } @Test @@ -1056,10 +1073,12 @@ public class NetworkMonitorTest { setStatus(mHttpConnection, 204); setApiContent(mCapportApiConnection, "{'captive': false," + "'venue-info-url': '" + TEST_VENUE_INFO_URL + "'}"); - runNetworkTest(CAPPORT_LINK_PROPERTIES, METERED_CAPABILITIES, VALIDATION_RESULT_PARTIAL); + runNetworkTest(makeCapportLPs(), METERED_CAPABILITIES, VALIDATION_RESULT_PARTIAL); - verify(mCallbacks).notifyCaptivePortalDataChanged(argThat(data -> - Uri.parse(TEST_VENUE_INFO_URL).equals(data.getVenueInfoUrl()))); + final ArgumentCaptor<CaptivePortalData> capportCaptor = ArgumentCaptor.forClass( + CaptivePortalData.class); + verify(mCallbacks).notifyCaptivePortalDataChanged(capportCaptor.capture()); + assertEquals(Uri.parse(TEST_VENUE_INFO_URL), capportCaptor.getValue().getVenueInfoUrl()); } @Test @@ -1069,11 +1088,12 @@ public class NetworkMonitorTest { setStatus(mHttpConnection, 204); setApiContent(mCapportApiConnection, "{'captive': false," + "'venue-info-url': '" + TEST_VENUE_INFO_URL + "'}"); - runNetworkTest(CAPPORT_LINK_PROPERTIES, METERED_CAPABILITIES, - VALIDATION_RESULT_VALID_ALL_PROBES); + runNetworkTest(makeCapportLPs(), METERED_CAPABILITIES, VALIDATION_RESULT_VALID_ALL_PROBES); - verify(mCallbacks).notifyCaptivePortalDataChanged(argThat(data -> - Uri.parse(TEST_VENUE_INFO_URL).equals(data.getVenueInfoUrl()))); + final ArgumentCaptor<CaptivePortalData> capportCaptor = ArgumentCaptor.forClass( + CaptivePortalData.class); + verify(mCallbacks).notifyCaptivePortalDataChanged(capportCaptor.capture()); + assertEquals(Uri.parse(TEST_VENUE_INFO_URL), capportCaptor.getValue().getVenueInfoUrl()); } @Test @@ -1082,20 +1102,22 @@ public class NetworkMonitorTest { setStatus(mHttpsConnection, 204); setPortal302(mHttpConnection); setApiContent(mCapportApiConnection, "{SomeInvalidText"); - runNetworkTest(CAPPORT_LINK_PROPERTIES, METERED_CAPABILITIES, VALIDATION_RESULT_PORTAL); + runNetworkTest(makeCapportLPs(), METERED_CAPABILITIES, VALIDATION_RESULT_PORTAL); verify(mCallbacks, never()).notifyCaptivePortalDataChanged(any()); verify(mHttpConnection).getResponseCode(); } - @Test + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testIsCaptivePortal_CapportApiNotSupported() throws Exception { + // Test that on a R+ device, if NetworkStack was compiled without CaptivePortalData support + // (built against Q), NetworkMonitor behaves as expected. assumeFalse(CaptivePortalDataShimImpl.isSupported()); setSslException(mHttpsConnection); setPortal302(mHttpConnection); setApiContent(mCapportApiConnection, "{'captive': false," + "'venue-info-url': '" + TEST_VENUE_INFO_URL + "'}"); - runNetworkTest(CAPPORT_LINK_PROPERTIES, METERED_CAPABILITIES, VALIDATION_RESULT_PORTAL); + runNetworkTest(makeCapportLPs(), METERED_CAPABILITIES, VALIDATION_RESULT_PORTAL); verify(mCallbacks, never()).notifyCaptivePortalDataChanged(any()); verify(mHttpConnection).getResponseCode(); |