diff options
Diffstat (limited to 'tests/robotests/src/test/java/com/google/android/enterprise/connectedapps/robotests/BothProfilesManualListenableFutureTest.java')
-rw-r--r-- | tests/robotests/src/test/java/com/google/android/enterprise/connectedapps/robotests/BothProfilesManualListenableFutureTest.java | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/tests/robotests/src/test/java/com/google/android/enterprise/connectedapps/robotests/BothProfilesManualListenableFutureTest.java b/tests/robotests/src/test/java/com/google/android/enterprise/connectedapps/robotests/BothProfilesManualListenableFutureTest.java new file mode 100644 index 0000000..a3ca7eb --- /dev/null +++ b/tests/robotests/src/test/java/com/google/android/enterprise/connectedapps/robotests/BothProfilesManualListenableFutureTest.java @@ -0,0 +1,234 @@ +/* + * Copyright 2021 Google LLC + * + * 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 + * + * https://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.google.android.enterprise.connectedapps.robotests; + +import static com.google.android.enterprise.connectedapps.SharedTestUtilities.INTERACT_ACROSS_USERS; +import static com.google.common.truth.Truth.assertThat; +import static org.robolectric.annotation.LooperMode.Mode.LEGACY; + +import android.app.Application; +import android.app.Service; +import android.os.Build.VERSION_CODES; +import android.os.IBinder; +import androidx.test.core.app.ApplicationProvider; +import com.google.android.enterprise.connectedapps.Profile; +import com.google.android.enterprise.connectedapps.RobolectricTestUtilities; +import com.google.android.enterprise.connectedapps.TestScheduledExecutorService; +import com.google.android.enterprise.connectedapps.testapp.configuration.TestApplication; +import com.google.android.enterprise.connectedapps.testapp.connector.TestProfileConnector; +import com.google.android.enterprise.connectedapps.testapp.types.ProfileTestCrossProfileType; +import com.google.android.enterprise.connectedapps.testapp.types.TestCrossProfileType; +import com.google.common.util.concurrent.ListenableFuture; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; +import org.robolectric.annotation.LooperMode; + +@LooperMode(LEGACY) +@RunWith(RobolectricTestRunner.class) +@Config(minSdk = VERSION_CODES.O) +public class BothProfilesManualListenableFutureTest { + private static final String STRING = "String"; + + private final Application context = ApplicationProvider.getApplicationContext(); + private final TestScheduledExecutorService scheduledExecutorService = + new TestScheduledExecutorService(); + private final TestProfileConnector testProfileConnector = + TestProfileConnector.create(context, scheduledExecutorService); + private final RobolectricTestUtilities testUtilities = + new RobolectricTestUtilities(testProfileConnector, scheduledExecutorService); + private final Profile currentProfileIdentifier = testProfileConnector.utils().getCurrentProfile(); + private final Profile otherProfileIdentifier = testProfileConnector.utils().getOtherProfile(); + private final ProfileTestCrossProfileType profileTestCrossProfileType = + ProfileTestCrossProfileType.create(testProfileConnector); + + @Before + public void setUp() { + Service profileAwareService = Robolectric.setupService(TestApplication.getService()); + testUtilities.initTests(); + IBinder binder = profileAwareService.onBind(/* intent= */ null); + testUtilities.setBinding(binder, RobolectricTestUtilities.TEST_CONNECTOR_CLASS_NAME); + testUtilities.createWorkUser(); + testUtilities.turnOnWorkProfile(); + testUtilities.setRunningOnPersonalProfile(); + testUtilities.setRequestsPermissions(INTERACT_ACROSS_USERS); + testUtilities.grantPermissions(INTERACT_ACROSS_USERS); + testUtilities.startConnectingAndWait(); + } + + @Test + public void both_listenableFuture_manualConnection_isBound_calledOnBothProfiles() + throws ExecutionException, InterruptedException { + testUtilities.startConnectingAndWait(); + testUtilities.turnOnWorkProfile(); + testUtilities.startConnectingAndWait(); + + profileTestCrossProfileType.both().listenableFutureVoidMethod().get(); + + // This calls on the same profile because of robolectric + assertThat(TestCrossProfileType.voidMethodCalls).isEqualTo(2); + } + + @Test + public void both_listenableFuture_manualConnection_isBound_resultContainsBothProfilesResults() + throws ExecutionException, InterruptedException { + testUtilities.startConnectingAndWait(); + testUtilities.turnOnWorkProfile(); + testUtilities.startConnectingAndWait(); + + Map<Profile, String> results = + profileTestCrossProfileType.both().listenableFutureIdentityStringMethod(STRING).get(); + + assertThat(results.get(currentProfileIdentifier)).isEqualTo(STRING); + assertThat(results.get(otherProfileIdentifier)).isEqualTo(STRING); + } + + @Test // This behaviour is expected right now but will change + public void both_listenableFuture_manualConnection_isBound_blockingMethod_blocks() { + testUtilities.startConnectingAndWait(); + testUtilities.turnOnWorkProfile(); + testUtilities.startConnectingAndWait(); + + ListenableFuture<Map<Profile, Void>> future = + profileTestCrossProfileType + .both() + .listenableFutureVoidMethodWithDelay(/* secondsDelay= */ 5); + + assertThat(future.isDone()).isTrue(); + } + + @Test + public void both_listenableFuture_manualConnection_isBound_nonblockingMethod_doesNotBlock() { + testUtilities.turnOnWorkProfile(); + testUtilities.startConnectingAndWait(); + + ListenableFuture<Map<Profile, Void>> future = + profileTestCrossProfileType + .both() + .listenableFutureVoidMethodWithNonBlockingDelay(/* secondsDelay= */ 5); + + assertThat(future.isDone()).isFalse(); + } + + @Test + public void both_listenableFuture_manualConnection_isBound_nonblockingMethod_doesCallback() { + testUtilities.turnOnWorkProfile(); + testUtilities.startConnectingAndWait(); + + ListenableFuture<Map<Profile, Void>> future = + profileTestCrossProfileType + .both() + .listenableFutureVoidMethodWithNonBlockingDelay(/* secondsDelay= */ 5); + testUtilities.advanceTimeBySeconds(10); + + assertThat(future.isDone()).isTrue(); + } + + @Test + public void both_listenableFuture_manualConnection_isNotBound_calledOnOnlyCurrentProfile() + throws ExecutionException, InterruptedException { + testUtilities.startConnectingAndWait(); + testUtilities.turnOffWorkProfile(); + + profileTestCrossProfileType.both().listenableFutureVoidMethod().get(); + + // This calls on the same profile because of robolectric + assertThat(TestCrossProfileType.voidMethodCalls).isEqualTo(1); + } + + @Test + public void + both_listenableFuture_manualConnection_isNotBound_resultContainsOnlyCurrentProfilesResult() + throws ExecutionException, InterruptedException { + testUtilities.startConnectingAndWait(); + testUtilities.turnOffWorkProfile(); + + Map<Profile, String> results = + profileTestCrossProfileType.both().listenableFutureIdentityStringMethod(STRING).get(); + + assertThat(results.get(currentProfileIdentifier)).isEqualTo(STRING); + assertThat(results.get(otherProfileIdentifier)).isEqualTo(null); + } + + @Test + public void both_listenableFuture_manualConnection_isBound_becomesUnbound_calledOnBothProfiles() { + testUtilities.turnOnWorkProfile(); + testUtilities.startConnectingAndWait(); + ListenableFuture<Map<Profile, Void>> unusedFuture = + profileTestCrossProfileType + .both() + .listenableFutureVoidMethodWithNonBlockingDelay(/* secondsDelay= */ 5); + + // Because of the way Robolectric currently works - the method is guaranteed to have executed + // before the work profile is turned off. This may change with later changes to the SDK so + // this test will be updated. + testUtilities.turnOffWorkProfile(); + + // This calls on the same profile because of robolectric + assertThat(TestCrossProfileType.voidMethodCalls).isEqualTo(2); + } + + @Test + public void both_listenableFuture_manualConnection_isBound_becomesUnbound_callbackFires() { + testUtilities.turnOnWorkProfile(); + testUtilities.startConnectingAndWait(); + ListenableFuture<Map<Profile, Void>> future = + profileTestCrossProfileType + .both() + .listenableFutureVoidMethodWithNonBlockingDelay(/* secondsDelay= */ 5); + + testUtilities.turnOffWorkProfile(); + + assertThat(future.isDone()).isTrue(); + } + + @Test + public void both_listenableFuture_manualConnection_profilesWithExceptionsAreNotIncludedInResults() + throws ExecutionException, InterruptedException { + testUtilities.startConnectingAndWait(); + ListenableFuture<Map<Profile, Void>> future = + profileTestCrossProfileType + .both() + .listenableFutureVoidMethodWhichSetsIllegalStateException(); + + assertThat(future.get()).isEmpty(); + } + + @Test + public void + both_listenableFuture_manualConnection_connectionDropsDuringCall_resultContainsOnlyCurrentProfilesResult() + throws ExecutionException, InterruptedException { + testUtilities.startConnectingAndWait(); + ListenableFuture<Map<Profile, String>> future = + profileTestCrossProfileType + .both() + .listenableFutureIdentityStringMethodWithNonBlockingDelay( + STRING, /* secondsDelay= */ 5); + testUtilities.advanceTimeBySeconds(2); + + testUtilities.turnOffWorkProfile(); + + Map<Profile, String> results = future.get(); + + assertThat(results).containsKey(currentProfileIdentifier); + assertThat(results).doesNotContainKey(otherProfileIdentifier); + } +} |