Add extensions from kotlinx.support libraries:

use for AutoCloseables: #KT-5899,
extensions for java.util.Stream.
This commit is contained in:
Ilya Gorbunov
2016-06-15 20:53:21 +03:00
parent d6261521ff
commit b16f46d932
10 changed files with 528 additions and 0 deletions
@@ -0,0 +1,35 @@
@file:JvmName("StandardJRE7Kt")
package kotlin
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
@kotlin.internal.InlineOnly
public inline fun <T : AutoCloseable, R> T.use(block: (T) -> R): R {
var closed = false
try {
return block(this)
} catch (e: Throwable) {
closed = true
@Suppress("NON_PUBLIC_CALL_FROM_PUBLIC_INLINE")
closeSuppressed(e)
throw e
} finally {
if (!closed) {
close()
}
}
}
/**
* Closes this [AutoCloseable] suppressing possible exception or error thrown by [AutoCloseable.close] function.
* The suppressed exception is added to the list of suppressed exceptions of [cause] exception.
*/
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
@kotlin.internal.InlineExposed
internal fun AutoCloseable.closeSuppressed(cause: Throwable) {
try {
close()
} catch (closeException: Throwable) {
cause.addSuppressed(closeException)
}
}
@@ -0,0 +1,86 @@
package kotlin.jdk7.test
import java.io.*
import org.junit.Test
import kotlin.test.*
class TryWithResourcesAutoCloseableTest {
class Resource(val faultyClose: Boolean = false) : AutoCloseable {
var isClosed = false
private set
override fun close() {
if (faultyClose)
throw IOException("Close failed")
isClosed = true
}
}
@Test fun success() {
val resource = Resource()
val result = resource.use { "ok" }
assertEquals("ok", result)
assertTrue(resource.isClosed)
}
@Test fun closeFails() {
val e = assertFails {
Resource(faultyClose = true).use { "" }
}
assertTrue(e is IOException)
}
@Test fun opFailsCloseSuccess() {
val e = assertFails {
Resource().use { error("op fail") }
}
assertTrue(e is IllegalStateException)
assertTrue(e.suppressed.isEmpty())
}
@Test fun opFailsCloseFails() {
val e = assertFails {
Resource(faultyClose = true).use { error("op fail") }
}
assertTrue(e is IllegalStateException)
assertTrue(e.suppressed.single() is IOException)
}
@Test fun opFailsCloseFailsTwice() {
val e = assertFails {
Resource(faultyClose = true).use { res1 ->
Resource(faultyClose = true).use { res2 ->
error("op fail")
}
}
}
assertTrue(e is IllegalStateException)
val suppressed = e.suppressed
assertEquals(2, suppressed.size)
assertTrue(suppressed.all { it is IOException })
}
@Test fun nonLocalReturnInBlock() {
fun Resource.operation(nonLocal: Boolean): String {
return use { if (nonLocal) return "nonLocal" else "local" }
}
Resource().let { resource ->
val result = resource.operation(nonLocal = false)
assertEquals("local", result)
assertTrue(resource.isClosed)
}
Resource().let { resource ->
val result = resource.operation(nonLocal = true)
assertEquals("nonLocal", result)
assertTrue(resource.isClosed)
}
}
}
@@ -0,0 +1,84 @@
package kotlin.jdk7.test
import java.io.*
import org.junit.Test
import kotlin.test.*
class TryWithResourcesCloseableTest {
class Resource(val faultyClose: Boolean = false) : Closeable {
var isClosed = false
private set
override fun close() {
if (faultyClose)
throw IOException("Close failed")
isClosed = true
}
}
@Test fun success() {
val resource = Resource()
val result = resource.use { "ok" }
assertEquals("ok", result)
assertTrue(resource.isClosed)
}
@Test fun closeFails() {
val e = assertFails {
Resource(faultyClose = true).use { "" }
}
assertTrue(e is IOException)
}
@Test fun opFailsCloseSuccess() {
val e = assertFails {
Resource().use { error("op fail") }
}
assertTrue(e is IllegalStateException)
assertTrue(e.suppressed.isEmpty())
}
@Test fun opFailsCloseFails() {
val e = assertFails {
Resource(faultyClose = true).use { error("op fail") }
}
assertTrue(e is IllegalStateException)
assertTrue(e.suppressed.single() is IOException)
}
@Test fun opFailsCloseFailsTwice() {
val e = assertFails {
Resource(faultyClose = true).use { res1 ->
Resource(faultyClose = true).use { res2 ->
error("op fail")
}
}
}
assertTrue(e is IllegalStateException)
val suppressed = e.suppressed
assertEquals(2, suppressed.size)
assertTrue(suppressed.all { it is IOException })
}
@Test fun nonLocalReturnInBlock() {
fun Resource.operation(nonLocal: Boolean): String {
return use { if (nonLocal) return "nonLocal" else "local" }
}
Resource().let { resource ->
val result = resource.operation(nonLocal = false)
assertEquals("local", result)
assertTrue(resource.isClosed)
}
Resource().let { resource ->
val result = resource.operation(nonLocal = true)
assertEquals("nonLocal", result)
assertTrue(resource.isClosed)
}
}
}