diff options
| author | 2023-05-08 21:44:38 +0000 | |
|---|---|---|
| committer | 2023-05-08 21:44:38 +0000 | |
| commit | e7e444ef214922959f410888959bb1cdfcd07b31 (patch) | |
| tree | 0b8729f369ae1a164f56b55fa960cbf8da56e70a /java/tests | |
| parent | 7b0a0f697c9f35c17394a5294ee76b2514a8deb5 (diff) | |
| parent | 56b29f80e91d5dcbeafb55d0193055ebead9d613 (diff) | |
Merge "Use a ViewState to preserve refinement state" into udc-dev am: 56b29f80e9
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/IntentResolver/+/22955375
Change-Id: I6d5a923d60feba91ed1a7cccdd6e4b1a9e2ef806
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
Diffstat (limited to 'java/tests')
3 files changed, 225 insertions, 44 deletions
diff --git a/java/tests/src/com/android/intentresolver/ChooserRefinementManagerTest.kt b/java/tests/src/com/android/intentresolver/ChooserRefinementManagerTest.kt index 50c37c7f..bd355c86 100644 --- a/java/tests/src/com/android/intentresolver/ChooserRefinementManagerTest.kt +++ b/java/tests/src/com/android/intentresolver/ChooserRefinementManagerTest.kt @@ -16,46 +16,227 @@ package com.android.intentresolver -import android.content.Context +import android.app.Activity +import android.app.Application import android.content.Intent import android.content.IntentSender +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.os.Message +import android.os.ResultReceiver +import androidx.lifecycle.Observer +import androidx.test.annotation.UiThreadTest import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.intentresolver.ChooserRefinementManager.RefinementCompletion +import com.android.intentresolver.chooser.ImmutableTargetInfo import com.android.intentresolver.chooser.TargetInfo +import com.google.common.truth.Truth.assertThat +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.Mockito -import java.util.function.Consumer -import org.junit.Assert.assertEquals @RunWith(AndroidJUnit4::class) +@UiThreadTest class ChooserRefinementManagerTest { - @Test - fun testMaybeHandleSelection() { - val intentSender = mock<IntentSender>() - val refinementManager = ChooserRefinementManager( - mock<Context>(), - intentSender, - Consumer<TargetInfo>{}, - Runnable{}) - - val intents = listOf(Intent(Intent.ACTION_VIEW), Intent(Intent.ACTION_EDIT)) - val targetInfo = mock<TargetInfo>{ - whenever(allSourceIntents).thenReturn(intents) + private val refinementManager = ChooserRefinementManager() + private val intentSender = mock<IntentSender>() + private val application = mock<Application>() + private val exampleSourceIntents = + listOf(Intent(Intent.ACTION_VIEW), Intent(Intent.ACTION_EDIT)) + private val exampleTargetInfo = + ImmutableTargetInfo.newBuilder().setAllSourceIntents(exampleSourceIntents).build() + + private val completionObserver = + object : Observer<RefinementCompletion> { + val failureCountDown = CountDownLatch(1) + val successCountDown = CountDownLatch(1) + var latestTargetInfo: TargetInfo? = null + + override fun onChanged(completion: RefinementCompletion) { + if (completion.consume()) { + val targetInfo = completion.targetInfo + if (targetInfo == null) { + failureCountDown.countDown() + } else { + latestTargetInfo = targetInfo + successCountDown.countDown() + } + } + } } - refinementManager.maybeHandleSelection(targetInfo) + /** Synchronously executes post() calls. */ + private class FakeHandler(looper: Looper) : Handler(looper) { + override fun sendMessageAtTime(msg: Message, uptimeMillis: Long): Boolean { + dispatchMessage(msg) + return true + } + } + + @Before + fun setup() { + refinementManager.refinementCompletion.observeForever(completionObserver) + } + + @Test + fun testTypicalRefinementFlow() { + assertThat( + refinementManager.maybeHandleSelection( + exampleTargetInfo, + intentSender, + application, + FakeHandler(Looper.myLooper()) + ) + ) + .isTrue() val intentCaptor = ArgumentCaptor.forClass(Intent::class.java) - Mockito.verify(intentSender).sendIntent( - any(), eq(0), intentCaptor.capture(), eq(null), eq(null)) + Mockito.verify(intentSender) + .sendIntent(any(), eq(0), intentCaptor.capture(), eq(null), eq(null)) val intent = intentCaptor.value - assertEquals(intents[0], intent.getParcelableExtra(Intent.EXTRA_INTENT, Intent::class.java)) + assertThat(intent?.getParcelableExtra(Intent.EXTRA_INTENT, Intent::class.java)) + .isEqualTo(exampleSourceIntents[0]) val alternates = - intent.getParcelableArrayExtra(Intent.EXTRA_ALTERNATE_INTENTS, Intent::class.java) - assertEquals(1, alternates?.size) - assertEquals(intents[1], alternates?.get(0)) + intent?.getParcelableArrayExtra(Intent.EXTRA_ALTERNATE_INTENTS, Intent::class.java) + assertThat(alternates?.size).isEqualTo(1) + assertThat(alternates?.get(0)).isEqualTo(exampleSourceIntents[1]) + + // Complete the refinement + val receiver = + intent?.getParcelableExtra(Intent.EXTRA_RESULT_RECEIVER, ResultReceiver::class.java) + val bundle = Bundle().apply { putParcelable(Intent.EXTRA_INTENT, exampleSourceIntents[0]) } + receiver?.send(Activity.RESULT_OK, bundle) + + assertThat(completionObserver.successCountDown.await(1000, TimeUnit.MILLISECONDS)).isTrue() + assertThat(completionObserver.latestTargetInfo?.resolvedIntent?.action) + .isEqualTo(Intent.ACTION_VIEW) + } + + @Test + fun testRefinementCancelled() { + assertThat( + refinementManager.maybeHandleSelection( + exampleTargetInfo, + intentSender, + application, + FakeHandler(Looper.myLooper()) + ) + ) + .isTrue() + + val intentCaptor = ArgumentCaptor.forClass(Intent::class.java) + Mockito.verify(intentSender) + .sendIntent(any(), eq(0), intentCaptor.capture(), eq(null), eq(null)) + + val intent = intentCaptor.value + + // Complete the refinement + val receiver = + intent?.getParcelableExtra(Intent.EXTRA_RESULT_RECEIVER, ResultReceiver::class.java) + val bundle = Bundle().apply { putParcelable(Intent.EXTRA_INTENT, exampleSourceIntents[0]) } + receiver?.send(Activity.RESULT_CANCELED, bundle) + + assertThat(completionObserver.failureCountDown.await(1000, TimeUnit.MILLISECONDS)).isTrue() + } + + @Test + fun testMaybeHandleSelection_noSourceIntents() { + assertThat( + refinementManager.maybeHandleSelection( + ImmutableTargetInfo.newBuilder().build(), + intentSender, + application, + FakeHandler(Looper.myLooper()) + ) + ) + .isFalse() + } + + @Test + fun testMaybeHandleSelection_suspended() { + val targetInfo = + ImmutableTargetInfo.newBuilder() + .setAllSourceIntents(exampleSourceIntents) + .setIsSuspended(true) + .build() + + assertThat( + refinementManager.maybeHandleSelection( + targetInfo, + intentSender, + application, + FakeHandler(Looper.myLooper()) + ) + ) + .isFalse() + } + + @Test + fun testMaybeHandleSelection_noIntentSender() { + assertThat( + refinementManager.maybeHandleSelection( + exampleTargetInfo, + /* IntentSender */ null, + application, + FakeHandler(Looper.myLooper()) + ) + ) + .isFalse() + } + + @Test + fun testConfigurationChangeDuringRefinement() { + assertThat( + refinementManager.maybeHandleSelection( + exampleTargetInfo, + intentSender, + application, + FakeHandler(Looper.myLooper()) + ) + ) + .isTrue() + + refinementManager.onActivityStop(/* config changing = */ true) + refinementManager.onActivityResume() + + assertThat(completionObserver.failureCountDown.count).isEqualTo(1) + } + + @Test + fun testResumeDuringRefinement() { + assertThat( + refinementManager.maybeHandleSelection( + exampleTargetInfo, + intentSender, + application, + FakeHandler(Looper.myLooper()!!) + ) + ) + .isTrue() + + refinementManager.onActivityStop(/* config changing = */ false) + // Resume during refinement but not during a config change, so finish the activity. + refinementManager.onActivityResume() + + // Call should be synchronous, don't need to await for this one. + assertThat(completionObserver.failureCountDown.count).isEqualTo(0) + } + + @Test + fun testRefinementCompletion() { + val refinementCompletion = RefinementCompletion(exampleTargetInfo) + assertThat(refinementCompletion.targetInfo).isEqualTo(exampleTargetInfo) + assertThat(refinementCompletion.consume()).isTrue() + assertThat(refinementCompletion.targetInfo).isEqualTo(exampleTargetInfo) + + // can only consume once. + assertThat(refinementCompletion.consume()).isFalse() } } diff --git a/java/tests/src/com/android/intentresolver/chooser/ImmutableTargetInfoTest.kt b/java/tests/src/com/android/intentresolver/chooser/ImmutableTargetInfoTest.kt index cebccaae..504cfd97 100644 --- a/java/tests/src/com/android/intentresolver/chooser/ImmutableTargetInfoTest.kt +++ b/java/tests/src/com/android/intentresolver/chooser/ImmutableTargetInfoTest.kt @@ -222,8 +222,8 @@ class ImmutableTargetInfoTest { .build() val info = originalInfo.tryToCloneWithAppliedRefinement(refinementIntent) - assertThat(info.baseIntentToSend.getBooleanExtra("ORIGINAL", false)).isTrue() - assertThat(info.baseIntentToSend.getBooleanExtra("REFINEMENT", false)).isTrue() + assertThat(info?.baseIntentToSend?.getBooleanExtra("ORIGINAL", false)).isTrue() + assertThat(info?.baseIntentToSend?.getBooleanExtra("REFINEMENT", false)).isTrue() } @Test @@ -245,9 +245,9 @@ class ImmutableTargetInfoTest { val info = infoWithReferrerFillIn.tryToCloneWithAppliedRefinement(refinementIntent) - assertThat(info.baseIntentToSend.getPackage()).isEqualTo("original") // Set all along. - assertThat(info.baseIntentToSend.action).isEqualTo("REFINE_ME") // Refinement wins. - assertThat(info.baseIntentToSend.type).isEqualTo("test/referrer") // Left for referrer. + assertThat(info?.baseIntentToSend?.getPackage()).isEqualTo("original") // Set all along. + assertThat(info?.baseIntentToSend?.action).isEqualTo("REFINE_ME") // Refinement wins. + assertThat(info?.baseIntentToSend?.type).isEqualTo("test/referrer") // Left for referrer. } @Test @@ -266,18 +266,18 @@ class ImmutableTargetInfoTest { .build() val refined1 = originalInfo.tryToCloneWithAppliedRefinement(refinementIntent1) - val refined2 = refined1.tryToCloneWithAppliedRefinement(refinementIntent2) // Cloned clone. + val refined2 = refined1?.tryToCloneWithAppliedRefinement(refinementIntent2) // Cloned clone. // Both clones get the same values filled in from the referrer intent. - assertThat(refined1.baseIntentToSend.getStringExtra("TEST")).isEqualTo("REFERRER") - assertThat(refined2.baseIntentToSend.getStringExtra("TEST")).isEqualTo("REFERRER") + assertThat(refined1?.baseIntentToSend?.getStringExtra("TEST")).isEqualTo("REFERRER") + assertThat(refined2?.baseIntentToSend?.getStringExtra("TEST")).isEqualTo("REFERRER") // Each clone has the respective value that was set in their own refinement request. - assertThat(refined1.baseIntentToSend.getStringExtra("TEST1")).isEqualTo("1") - assertThat(refined2.baseIntentToSend.getStringExtra("TEST2")).isEqualTo("2") + assertThat(refined1?.baseIntentToSend?.getStringExtra("TEST1")).isEqualTo("1") + assertThat(refined2?.baseIntentToSend?.getStringExtra("TEST2")).isEqualTo("2") // The clones don't have the data from each other's refinements, even though the intent // field is empty (thus able to be populated by filling-in). - assertThat(refined1.baseIntentToSend.getStringExtra("TEST2")).isNull() - assertThat(refined2.baseIntentToSend.getStringExtra("TEST1")).isNull() + assertThat(refined1?.baseIntentToSend?.getStringExtra("TEST2")).isNull() + assertThat(refined2?.baseIntentToSend?.getStringExtra("TEST1")).isNull() } @Test @@ -301,15 +301,15 @@ class ImmutableTargetInfoTest { refinement.putExtra("refinement", true) val refinedResult = originalInfo.tryToCloneWithAppliedRefinement(refinement) - assertThat(refinedResult.baseIntentToSend.getBooleanExtra("refinement", false)).isTrue() - assertThat(refinedResult.baseIntentToSend.getBooleanExtra("targetAlternate", false)) + assertThat(refinedResult?.baseIntentToSend?.getBooleanExtra("refinement", false)).isTrue() + assertThat(refinedResult?.baseIntentToSend?.getBooleanExtra("targetAlternate", false)) .isTrue() // None of the other source intents got merged in (not even the later one that matched): - assertThat(refinedResult.baseIntentToSend.getBooleanExtra("originalIntent", false)) + assertThat(refinedResult?.baseIntentToSend?.getBooleanExtra("originalIntent", false)) .isFalse() - assertThat(refinedResult.baseIntentToSend.getBooleanExtra("mismatchedAlternate", false)) + assertThat(refinedResult?.baseIntentToSend?.getBooleanExtra("mismatchedAlternate", false)) .isFalse() - assertThat(refinedResult.baseIntentToSend.getBooleanExtra("extraMatch", false)).isFalse() + assertThat(refinedResult?.baseIntentToSend?.getBooleanExtra("extraMatch", false)).isFalse() } @Test diff --git a/java/tests/src/com/android/intentresolver/chooser/TargetInfoTest.kt b/java/tests/src/com/android/intentresolver/chooser/TargetInfoTest.kt index 886e32df..f9d3dd96 100644 --- a/java/tests/src/com/android/intentresolver/chooser/TargetInfoTest.kt +++ b/java/tests/src/com/android/intentresolver/chooser/TargetInfoTest.kt @@ -234,15 +234,15 @@ class TargetInfoTest { val refinedResult = originalInfo.tryToCloneWithAppliedRefinement(refinement) // Note `DisplayResolveInfo` targets merge refinements directly into their `resolvedIntent`. - assertThat(refinedResult.resolvedIntent.getBooleanExtra("refinement", false)).isTrue() - assertThat(refinedResult.resolvedIntent.getBooleanExtra("targetAlternate", false)) + assertThat(refinedResult?.resolvedIntent?.getBooleanExtra("refinement", false)).isTrue() + assertThat(refinedResult?.resolvedIntent?.getBooleanExtra("targetAlternate", false)) .isTrue() // None of the other source intents got merged in (not even the later one that matched): - assertThat(refinedResult.resolvedIntent.getBooleanExtra("originalIntent", false)) + assertThat(refinedResult?.resolvedIntent?.getBooleanExtra("originalIntent", false)) .isFalse() - assertThat(refinedResult.resolvedIntent.getBooleanExtra("mismatchedAlternate", false)) + assertThat(refinedResult?.resolvedIntent?.getBooleanExtra("mismatchedAlternate", false)) .isFalse() - assertThat(refinedResult.resolvedIntent.getBooleanExtra("extraMatch", false)).isFalse() + assertThat(refinedResult?.resolvedIntent?.getBooleanExtra("extraMatch", false)).isFalse() } @Test |