Bug 1463484 - 2. Add GeckoResponse helpers for tests; r=me
Use the external delegate functionality to implement helpers for
GeckoResponse, so tests can easily wait for responses to come back, in
order to test APIs that use GeckoResponse.
MozReview-Commit-ID: IhxWqGtyJwd
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt
@@ -11,16 +11,17 @@ import org.mozilla.geckoview.GeckoSessio
import org.mozilla.geckoview.GeckoSessionSettings
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule
import org.hamcrest.Matcher
import org.hamcrest.Matchers
import org.junit.Assume.assumeThat
import org.junit.Rule
import org.junit.rules.ErrorCollector
+import org.mozilla.geckoview.GeckoResponse
import kotlin.reflect.KClass
/**
* Common base class for tests using GeckoSessionTestRule,
* providing the test rule and other utilities.
*/
open class BaseSessionTest(noErrorCollector: Boolean = false) {
@@ -55,16 +56,28 @@ open class BaseSessionTest(noErrorCollec
}
fun <T> forEachCall(vararg values: T): T = sessionRule.forEachCall(*values)
fun getTestBytes(path: String) =
InstrumentationRegistry.getTargetContext().resources.assets
.open(path.removePrefix("/assets/")).readBytes()
+ @Suppress("UNCHECKED_CAST")
+ fun <T> delegateResponseDuringNextWait(lambda: (GeckoResponse<T>) -> Unit) =
+ sessionRule.addExternalDelegateDuringNextWait(
+ GeckoResponse::class.java as Class<GeckoResponse<T>>,
+ lambda, {}, GeckoResponse {})
+
+ @Suppress("UNCHECKED_CAST")
+ fun <T> delegateResponseUntilTestEnd(lambda: (GeckoResponse<T>) -> Unit) =
+ sessionRule.addExternalDelegateUntilTestEnd(
+ GeckoResponse::class.java as Class<GeckoResponse<T>>,
+ lambda, {}, GeckoResponse {})
+
val GeckoSession.isRemote
get() = this.settings.getBoolean(GeckoSessionSettings.USE_MULTIPROCESS)
fun GeckoSession.loadTestPath(path: String) =
this.loadUri(GeckoSessionTestRule.APK_URI_PREFIX + path.removePrefix("/"))
inline fun GeckoSession.toParcel(lambda: (Parcel) -> Unit) {
val parcel = Parcel.obtain()
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt
@@ -1,14 +1,15 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
package org.mozilla.geckoview.test
+import org.mozilla.geckoview.GeckoResponse
import org.mozilla.geckoview.GeckoSession
import org.mozilla.geckoview.GeckoSessionSettings
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.ClosedSessionAtStart
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.NullDelegate
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.RejectedPromiseException
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.Setting
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.TimeoutException
@@ -1640,9 +1641,40 @@ class GeckoSessionTestRuleTest : BaseSes
mainSession.reload()
mainSession.waitForPageStop()
assertThat("Test delegate should still be registered", delegate, notNullValue())
assertThat("Test delegate return value should be correct",
delegate?.onDelegate("", ""), equalTo(42))
sessionRule.performTestEndCheck()
}
+
+ @Test fun delegateResponse() {
+ var testResponse: GeckoResponse<Boolean>? = null
+ var waitResponse: GeckoResponse<Int>? = null
+
+ delegateResponseUntilTestEnd<Boolean> { testResponse = it }
+ delegateResponseDuringNextWait<Int> { waitResponse = it }
+ assertThat("Test response should be set", testResponse, notNullValue())
+ assertThat("Wait response should be set", waitResponse, notNullValue())
+
+ var count = 0
+ waitResponse?.respond(1)
+ waitResponse?.respond(2)
+ waitResponse?.respond(3)
+ sessionRule.waitUntilCalled(GeckoResponse<Int> @AssertCalled(count = 3) {
+ assertThat("Wait response should be correct",
+ it, equalTo(forEachCall(1, 2, 3)))
+ count++
+ })
+ assertThat("Wait response count should be correct", count, equalTo(3))
+
+ count = 0
+ testResponse?.respond(true)
+ testResponse?.respond(false)
+ sessionRule.waitUntilCalled(GeckoResponse<Boolean> @AssertCalled(count = 2) {
+ assertThat("Test response should be correct",
+ it, equalTo(forEachCall(true, false)))
+ count++
+ })
+ assertThat("Test response count should be correct", count, equalTo(2))
+ }
}
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
@@ -794,29 +794,33 @@ public class GeckoSessionTestRule extend
call.incrementCounter();
assertOrder(call, mOrder);
mOrder = Math.max(call.getOrder(), mOrder);
return call;
}
}
/* package */ static AssertCalled getAssertCalled(final Method method, final Object callback) {
- final AssertCalled annotation = method.getAnnotation(AssertCalled.class);
+ AssertCalled annotation = method.getAnnotation(AssertCalled.class);
if (annotation != null) {
return annotation;
}
// Some Kotlin lambdas have an invoke method that carries the annotation,
// instead of the interface method carrying the annotation.
- try {
- return callback.getClass().getDeclaredMethod(
- "invoke", method.getParameterTypes()).getAnnotation(AssertCalled.class);
- } catch (final NoSuchMethodException e) {
- return null;
+ for (final Method invokeMethod : callback.getClass().getDeclaredMethods()) {
+ if (!"invoke".equals(invokeMethod.getName())) {
+ continue;
+ }
+ annotation = invokeMethod.getAnnotation(AssertCalled.class);
+ if (annotation != null) {
+ return annotation;
+ }
}
+ return null;
}
private static void addCallbackClasses(final List<Class<?>> list, final Class<?> ifce) {
if (!Callbacks.class.equals(ifce.getDeclaringClass())) {
list.add(ifce);
return;
}
final Class<?>[] superIfces = ifce.getInterfaces();