diff options
Diffstat (limited to 'tests/robotests/src/com/android/mms/service/MmsNetworkManagerTest.java')
-rw-r--r-- | tests/robotests/src/com/android/mms/service/MmsNetworkManagerTest.java | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/tests/robotests/src/com/android/mms/service/MmsNetworkManagerTest.java b/tests/robotests/src/com/android/mms/service/MmsNetworkManagerTest.java new file mode 100644 index 0000000..c2d3e05 --- /dev/null +++ b/tests/robotests/src/com/android/mms/service/MmsNetworkManagerTest.java @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.mms.service; + +import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.fail; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.ConnectivityManager.NetworkCallback; +import android.net.Network; +import android.net.NetworkCapabilities; +import android.net.NetworkInfo; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +@RunWith(RobolectricTestRunner.class) +public final class MmsNetworkManagerTest { + private static final int TEST_SUBID = 1234; + private static final int CALLBACK_TIMEOUT_MS = 3000; + private static final int NETWORK_ACQUIRE_TIMEOUT_MS = 5000; + + private static final String MMS_APN = "mmsapn"; + private static final String MMS_APN2 = "mmsapn2"; + private static final NetworkCapabilities SUSPEND_NC = new NetworkCapabilities.Builder().build(); + private static final NetworkCapabilities USABLE_NC = + new NetworkCapabilities.Builder().addCapability(NET_CAPABILITY_NOT_SUSPENDED).build(); + + @Mock Network mTestNetwork; + @Mock Network mTestNetwork2; + @Mock NetworkInfo mNetworkInfo; + @Mock NetworkInfo mNetworkInfo2; + @Mock Context mCtx; + @Mock ConnectivityManager mCm; + @Mock MmsNetworkManager.Dependencies mDeps; + + + private MmsNetworkManager mMnm; + private final ExecutorService mExecutor = Executors.newSingleThreadExecutor(); + private final AtomicInteger mRequestId = new AtomicInteger(1); + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + + doReturn(mCm).when(mCtx).getSystemService(Context.CONNECTIVITY_SERVICE); + doReturn(mCm).when(mCtx).getSystemService(ConnectivityManager.class); + doReturn(1).when(mDeps).getPhoneId(anyInt()); + doReturn(mNetworkInfo).when(mCm).getNetworkInfo(eq(mTestNetwork)); + doReturn(MMS_APN).when(mNetworkInfo).getExtraInfo(); + doReturn(mNetworkInfo2).when(mCm).getNetworkInfo(eq(mTestNetwork2)); + doReturn(MMS_APN2).when(mNetworkInfo2).getExtraInfo(); + doReturn(NETWORK_ACQUIRE_TIMEOUT_MS).when(mDeps).getNetworkRequestTimeoutMillis(); + doReturn(NETWORK_ACQUIRE_TIMEOUT_MS).when(mDeps).getAdditionalNetworkAcquireTimeoutMillis(); + + mMnm = new MmsNetworkManager(mCtx, TEST_SUBID, mDeps); + } + + @Test + public void testAvailableNetwork_newNetworkAvailable() throws Exception { + acquireAvailableNetworkAndGetCallback( + mTestNetwork /* expectNetwork */, MMS_APN /* expectApn */); + } + + @Test + public void testAvailableNetwork_newNetworkIsSuspend() throws Exception { + final ArgumentCaptor<NetworkCallback> callbackCaptor = + ArgumentCaptor.forClass(NetworkCallback.class); + final CompletableFuture<String> future = + acquireNetwork(Integer.toString(mRequestId.getAndIncrement())); + verify(mCm, timeout(CALLBACK_TIMEOUT_MS).times(1)) + .requestNetwork(any(), callbackCaptor.capture(), anyInt()); + final NetworkCallback callback = callbackCaptor.getValue(); + + callback.onCapabilitiesChanged(mTestNetwork, SUSPEND_NC); + assertFalse(future.isDone()); + // mNetwork should be null. + assertEquals(null, mMnm.getApnName()); + verify(mCm, never()).unregisterNetworkCallback(eq(callback)); + } + + @Test + public void testAvailableNetwork_networkSuspendThenResume() throws Exception { + final NetworkCallback callback = acquireAvailableNetworkAndGetCallback( + mTestNetwork /* expectNetwork */, MMS_APN /* expectApn */); + + // Network becomes suspended. mNetwork should be null. + callback.onCapabilitiesChanged(mTestNetwork, SUSPEND_NC); + assertEquals(null, mMnm.getApnName()); + verify(mCm, never()).unregisterNetworkCallback(eq(callback)); + + // Network resume + callback.onCapabilitiesChanged(mTestNetwork, USABLE_NC); + assertEquals(MMS_APN, mMnm.getApnName()); + } + + @Test + public void testAvailableNetwork_networkReplaced() throws Exception { + final NetworkCallback callback = acquireAvailableNetworkAndGetCallback( + mTestNetwork /* expectNetwork */, MMS_APN /* expectApn */); + + // Previous network lost. Callback will not release to wait for possible network. + callback.onLost(mTestNetwork); + verify(mCm, never()).unregisterNetworkCallback(eq(callback)); + // New mTestNetwork2 available + callback.onCapabilitiesChanged(mTestNetwork2, USABLE_NC); + assertEquals(MMS_APN2, mMnm.getApnName()); + } + + @Test + public void testAvailableNetwork_networkBecomeSuspend() throws Exception { + final NetworkCallback callback = acquireAvailableNetworkAndGetCallback( + mTestNetwork /* expectNetwork */, MMS_APN /* expectApn */); + + callback.onCapabilitiesChanged(mTestNetwork, SUSPEND_NC); + // mNetwork should be null. + assertEquals(null, mMnm.getApnName()); + // Callback will not release to wait for possible network. + verify(mCm, never()).unregisterNetworkCallback(eq(callback)); + } + + @Test + public void testAvailableNetwork_networkUnavailable() throws Exception { + doReturn(100).when(mDeps).getNetworkRequestTimeoutMillis(); + doReturn(100).when(mDeps).getAdditionalNetworkAcquireTimeoutMillis(); + final ArgumentCaptor<NetworkCallback> callbackCaptor = + ArgumentCaptor.forClass(NetworkCallback.class); + final CompletableFuture<String> future = + acquireNetwork(Integer.toString(mRequestId.getAndIncrement())); + verify(mCm, timeout(CALLBACK_TIMEOUT_MS).times(1)) + .requestNetwork(any(), callbackCaptor.capture(), anyInt()); + final NetworkCallback callback = callbackCaptor.getValue(); + + assertFalse(future.isDone()); + // No network available after 100+100 ms. Callback will be released. + verify(mCm, timeout(CALLBACK_TIMEOUT_MS).times(1)) + .unregisterNetworkCallback(eq(callback)); + + // mNetwork should be null. + assertEquals(null, mMnm.getApnName()); + } + + @Test + public void testAvailableNetwork_newNetworkSuspendedEventuallyReleased() throws Exception { + doReturn(100).when(mDeps).getNetworkRequestTimeoutMillis(); + doReturn(100).when(mDeps).getAdditionalNetworkAcquireTimeoutMillis(); + final ArgumentCaptor<NetworkCallback> callbackCaptor = + ArgumentCaptor.forClass(NetworkCallback.class); + final CompletableFuture<String> future = + acquireNetwork(Integer.toString(mRequestId.getAndIncrement())); + verify(mCm, timeout(CALLBACK_TIMEOUT_MS).times(1)) + .requestNetwork(any(), callbackCaptor.capture(), anyInt()); + final NetworkCallback callback = callbackCaptor.getValue(); + + // New network but not a usable network. + callback.onCapabilitiesChanged(mTestNetwork, SUSPEND_NC); + + assertFalse(future.isDone()); + // No network available after 100+100 ms. Callback will be released. + verify(mCm, timeout(CALLBACK_TIMEOUT_MS).times(1)) + .unregisterNetworkCallback(eq(callback)); + + // mNetwork should be null. + assertEquals(null, mMnm.getApnName()); + } + + private NetworkCallback acquireAvailableNetworkAndGetCallback( + Network expectNetwork, String expectApn) throws Exception { + final ArgumentCaptor<NetworkCallback> callbackCaptor = + ArgumentCaptor.forClass(NetworkCallback.class); + final CompletableFuture<String> future = + acquireNetwork(Integer.toString(mRequestId.getAndIncrement())); + verify(mCm, timeout(CALLBACK_TIMEOUT_MS).times(1)) + .requestNetwork(any(), callbackCaptor.capture(), anyInt()); + final NetworkCallback callback = callbackCaptor.getValue(); + + // Network available + callback.onCapabilitiesChanged(expectNetwork, USABLE_NC); + assertEquals(expectApn, future.get(CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS)); + return callbackCaptor.getValue(); + } + + private CompletableFuture<String> acquireNetwork(String requestId) { + final CompletableFuture<String> future = new CompletableFuture(); + + mExecutor.execute(() -> { + try { + mMnm.acquireNetwork(requestId); + future.complete(mMnm.getApnName()); + android.util.Log.d("MmsNetworkManagerTest", "acquireNetwork done"); + } catch (Exception e) { + fail("Acquire network fail"); + } + }); + + return future; + } +} |