tryTest to return its last evaluated expression

This is the same thing try{} does, and allows to lift
return out of tryTest.

This allows syntaxes like :
fun foo() = try {
    "Foo";
  } cleanup {
    doSomeCleanup()
  }
}

val network = try {
    registerNetworkCallback
    callback.getNetwork()
  } cleanup {
    unregisterNetworkCallback
  }
}

Note: bypassing ktlint because of b/185077240

Test: FrameworksNetTests
Change-Id: Ib8f6fde7ccfd62fdcb3c1e3b7b03909ed94d4b23
This commit is contained in:
Chalard Jean 2021-11-22 19:28:34 +09:00
commit b6fdf63095
4 changed files with 59 additions and 36 deletions

View file

@ -34,15 +34,17 @@ class CleanupTest {
@Test
fun testNotThrow() {
var x = 1
tryTest {
val result = tryTest {
x = 2
Log.e(TAG, "Do nothing")
6
} cleanup {
assertTrue(x == 2)
x = 3
Log.e(TAG, "Do nothing")
}
assertTrue(x == 3)
assertTrue(result == 6)
}
@Test
@ -99,4 +101,9 @@ class CleanupTest {
assertTrue(thrown.suppressedExceptions[0] is TestException2)
assertTrue(x == 4)
}
@Test
fun testReturn() {
assertTrue(6 == tryTest { 6 } cleanup { Log.e(TAG, "tested") })
}
}

View file

@ -35,14 +35,16 @@ public class CleanupTestJava {
@Test
public void testNotThrow() {
final AtomicInteger x = new AtomicInteger(1);
testAndCleanup(() -> {
final int a = testAndCleanup(() -> {
x.compareAndSet(1, 2);
Log.e(TAG, "Do nothing");
return 6;
}, () -> {
x.compareAndSet(2, 3);
Log.e(TAG, "Do nothing");
});
assertEquals(3, x.get());
assertEquals(6, a);
}
@Test

View file

@ -42,26 +42,34 @@ java_library {
}
java_library {
// Consider using net-tests-utils instead if writing device code.
// That library has a lot more useful tools into it for users that
// work on Android and includes this lib.
name: "net-tests-utils-host-device-common",
srcs: [
"hostdevice/**/*.java",
"hostdevice/**/*.kt",
],
host_supported: true,
visibility: [
"//frameworks/libs/net/common/tests:__subpackages__",
"//frameworks/libs/net/client-libs/tests:__subpackages__",
],
libs: [
"jsr305",
],
static_libs: [
"kotlin-test"
],
lint: { strict_updatability_linting: true },
// Consider using net-tests-utils instead if writing device code.
// That library has a lot more useful tools into it for users that
// work on Android and includes this lib.
name: "net-tests-utils-host-device-common",
srcs: [
"hostdevice/**/*.java",
"hostdevice/**/*.kt",
],
host_supported: true,
visibility: [
"//frameworks/libs/net/common/tests:__subpackages__",
"//frameworks/libs/net/client-libs/tests:__subpackages__",
],
// sc-mainline-prod uses an old version of Kotlin that used
// to reserve the right to make breaking changes to the
// Result type and disallowed returning an instance of it.
// Later versions allowed this and there was never a change,
// so no matter the version returning Result is always fine,
// but on sc-mainline-prod the compiler rejects it without
// the following flag.
kotlincflags: ["-Xallow-result-return-type"],
libs: [
"jsr305",
],
static_libs: [
"kotlin-test"
],
lint: { strict_updatability_linting: true },
}
java_test_host {

View file

@ -19,6 +19,7 @@
package com.android.testutils
import com.android.testutils.ExceptionUtils.ThrowingRunnable
import com.android.testutils.ExceptionUtils.ThrowingSupplier
import javax.annotation.CheckReturnValue
/**
@ -59,11 +60,15 @@ import javax.annotation.CheckReturnValue
* cleanup code
* });
*/
class ExceptionCleanupBlock(val originalException: Exception?) {
inline infix fun cleanup(block: () -> Unit) {
// sc-mainline-prod has an older kotlin that doesn't know about value classes. TODO : Change this
// to "value class" when aosp no longer merges into sc-mainline-prod.
@Suppress("INLINE_CLASS_DEPRECATED")
inline class ExceptionCleanupBlock<T>(val result: Result<T>) {
inline infix fun cleanup(block: () -> Unit): T {
try {
block()
} catch (e: Exception) {
val originalException = result.exceptionOrNull()
if (null == originalException) {
throw e
} else {
@ -71,25 +76,26 @@ class ExceptionCleanupBlock(val originalException: Exception?) {
throw originalException
}
}
if (null != originalException) throw originalException
return result.getOrThrow()
}
}
@CheckReturnValue
fun tryTest(block: () -> Unit): ExceptionCleanupBlock {
try {
block()
} catch (e: Exception) {
return ExceptionCleanupBlock(e)
}
return ExceptionCleanupBlock(null)
}
fun <T> tryTest(block: () -> T) = ExceptionCleanupBlock(
try {
Result.success(block())
} catch (e: Exception) {
Result.failure(e)
})
// Java support
fun testAndCleanup(tryBlock: ThrowingRunnable, cleanupBlock: ThrowingRunnable) {
tryTest {
tryBlock.run()
fun <T> testAndCleanup(tryBlock: ThrowingSupplier<T>, cleanupBlock: ThrowingRunnable): T {
return tryTest {
tryBlock.get()
} cleanup {
cleanupBlock.run()
}
}
fun testAndCleanup(tryBlock: ThrowingRunnable, cleanupBlock: ThrowingRunnable) {
return testAndCleanup(ThrowingSupplier { tryBlock.run() }, cleanupBlock)
}