| /* | |
| * Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. | |
| * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. | |
| */ | |
| package test.autoCloseable | |
| import kotlin.test.* | |
| class UseAutoCloseableResourceTest { | |
| class Resource(val faultyClose: Boolean = false) : AutoCloseable { | |
| var isClosed = false | |
| private set | |
| override fun close() { | |
| if (faultyClose) | |
| throw ResourceCloseException("Close failed") | |
| isClosed = true | |
| } | |
| } | |
| class ResourceCloseException(message: String) : Exception(message) | |
| @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 { it.isClosed } | |
| } | |
| assertTrue(e is ResourceCloseException) | |
| } | |
| @Test fun opFailsCloseSuccess() { | |
| val e = assertFails { | |
| Resource().use { error("op fail") } | |
| } | |
| assertTrue(e is IllegalStateException) | |
| assertTrue(e.suppressedExceptions.isEmpty()) | |
| } | |
| @Test fun opFailsCloseFails() { | |
| val e = assertFails { | |
| Resource(faultyClose = true).use { error("op fail") } | |
| } | |
| assertTrue(e is IllegalStateException) | |
| assertTrue(e.suppressedExceptions.single() is ResourceCloseException) | |
| } | |
| @Test fun opFailsCloseFailsTwice() { | |
| val e = assertFails { | |
| Resource(faultyClose = true).use { _ -> | |
| Resource(faultyClose = true).use { _ -> | |
| error("op fail") | |
| } | |
| } | |
| } | |
| assertTrue(e is IllegalStateException) | |
| val suppressed = e.suppressedExceptions | |
| assertEquals(2, suppressed.size) | |
| assertTrue(suppressed.all { it is ResourceCloseException }) | |
| } | |
| @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) | |
| } | |
| } | |
| @Test fun nullableResourceSuccess() { | |
| val resource: Resource? = null | |
| val result = resource.use { "ok" } | |
| assertEquals("ok", result) | |
| } | |
| @Test fun nullableResourceOpFails() { | |
| val resource: Resource? = null | |
| val e = assertFails { | |
| resource.use { requireNotNull(it) } | |
| } | |
| assertTrue(e is IllegalArgumentException) | |
| assertTrue(e.suppressedExceptions.isEmpty()) | |
| } | |
| @Test | |
| fun contractCallsInPlace() { | |
| val i: Int | |
| Resource().use { _ -> | |
| Resource().use { _ -> | |
| i = 1 | |
| } | |
| } | |
| assertEquals(1, i) | |
| } | |
| } |