Enabled disabled non-local returns in stdlib
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.Callable
|
||||
import java.util.concurrent.Future
|
||||
|
||||
val count: Int = 10;
|
||||
var index: Int = 0;
|
||||
val doneSignal = CountDownLatch(count)
|
||||
val startSignal = CountDownLatch(1);
|
||||
val mutex: Any = Object()
|
||||
val results = arrayListOf<Int>()
|
||||
val executorService = Executors.newFixedThreadPool(count)
|
||||
|
||||
class MyException(message: String): Exception(message)
|
||||
|
||||
enum class ExecutionType {
|
||||
LOCAL
|
||||
NON_LOCAL_SIMPLE
|
||||
NON_LOCAL_EXCEPTION
|
||||
NON_LOCAL_FINALLY
|
||||
NON_LOCAL_EXCEPTION_AND_FINALLY
|
||||
NON_LOCAL_EXCEPTION_AND_FINALLY_WITH_RETURN
|
||||
NON_LOCAL_NESTED
|
||||
}
|
||||
|
||||
class TestLocal(val name: String, val executionType: ExecutionType) : Callable<String> {
|
||||
|
||||
override fun call(): String {
|
||||
startSignal.await()
|
||||
return when (executionType) {
|
||||
is ExecutionType.LOCAL -> local()
|
||||
is ExecutionType.NON_LOCAL_SIMPLE -> nonLocalSimple()
|
||||
is ExecutionType.NON_LOCAL_EXCEPTION -> nonLocalWithException()
|
||||
is ExecutionType.NON_LOCAL_FINALLY -> nonLocalWithFinally()
|
||||
is ExecutionType.NON_LOCAL_EXCEPTION_AND_FINALLY -> nonLocalWithExceptionAndFinally()
|
||||
is ExecutionType.NON_LOCAL_EXCEPTION_AND_FINALLY_WITH_RETURN -> nonLocalWithExceptionAndFinallyWithReturn()
|
||||
is ExecutionType.NON_LOCAL_NESTED -> nonLocalNested()
|
||||
else -> "fail"
|
||||
}
|
||||
}
|
||||
|
||||
private fun underMutexFun() {
|
||||
results.add(++index);
|
||||
doneSignal.countDown()
|
||||
}
|
||||
|
||||
fun local(): String {
|
||||
synchronized(mutex) {
|
||||
underMutexFun()
|
||||
}
|
||||
return executionType.toString()
|
||||
}
|
||||
|
||||
|
||||
fun nonLocalSimple(): String {
|
||||
synchronized(mutex) {
|
||||
underMutexFun()
|
||||
return executionType.name()
|
||||
}
|
||||
return "fail"
|
||||
}
|
||||
|
||||
fun nonLocalWithException(): String {
|
||||
synchronized(mutex) {
|
||||
try {
|
||||
underMutexFun()
|
||||
throw MyException(executionType.name())
|
||||
} catch (e: MyException) {
|
||||
return e.getMessage()!!
|
||||
}
|
||||
}
|
||||
return "fail"
|
||||
}
|
||||
|
||||
fun nonLocalWithFinally(): String {
|
||||
synchronized(mutex) {
|
||||
try {
|
||||
underMutexFun()
|
||||
return "fail"
|
||||
} finally {
|
||||
return executionType.name()
|
||||
}
|
||||
}
|
||||
return "fail"
|
||||
}
|
||||
|
||||
fun nonLocalWithExceptionAndFinally(): String {
|
||||
synchronized(mutex) {
|
||||
try {
|
||||
underMutexFun()
|
||||
throw MyException(executionType.name())
|
||||
} catch (e: MyException) {
|
||||
return e.getMessage()!!
|
||||
} finally {
|
||||
"123"
|
||||
}
|
||||
}
|
||||
return "fail"
|
||||
}
|
||||
|
||||
fun nonLocalWithExceptionAndFinallyWithReturn(): String {
|
||||
synchronized(mutex) {
|
||||
try {
|
||||
underMutexFun()
|
||||
throw MyException(executionType.name())
|
||||
} catch (e: MyException) {
|
||||
return "fail1"
|
||||
} finally {
|
||||
return executionType.name()
|
||||
}
|
||||
}
|
||||
return "fail"
|
||||
}
|
||||
|
||||
fun nonLocalNested(): String {
|
||||
synchronized(mutex) {
|
||||
try {
|
||||
try {
|
||||
underMutexFun()
|
||||
throw MyException(executionType.name())
|
||||
} catch (e: MyException) {
|
||||
return "fail1"
|
||||
} finally {
|
||||
return executionType.name()
|
||||
}
|
||||
} finally {
|
||||
val p = 1 + 1
|
||||
}
|
||||
}
|
||||
return "fail"
|
||||
}
|
||||
}
|
||||
|
||||
fun testTemplate(type: ExecutionType, producer: (Int) -> Callable<String>): String {
|
||||
|
||||
try {
|
||||
val futures = arrayListOf<Future<String>>()
|
||||
for (i in 1..count) {
|
||||
futures.add(executorService.submit (producer(i)))
|
||||
}
|
||||
|
||||
startSignal.countDown()
|
||||
val b = doneSignal.await(10, TimeUnit.SECONDS)
|
||||
if (!b) return "fail: processes not finished"
|
||||
|
||||
for (i in 1..count) {
|
||||
if (results[i - 1] != i)
|
||||
return "fail $i != ${results[i]}: synchronization not works : " + results.joinToString()
|
||||
}
|
||||
|
||||
for (f in futures) {
|
||||
if (f.get() != type.name()) return "failed result ${f.get()} != ${type.name()}"
|
||||
}
|
||||
} finally {
|
||||
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun runTest(type: ExecutionType): String {
|
||||
return testTemplate (type) { TestLocal(it.toString(), type) }
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
try {
|
||||
for (type in ExecutionType.values()) {
|
||||
val result = runTest(type)
|
||||
if (result != "OK") return "fail on $type execution: $result"
|
||||
}
|
||||
} finally {
|
||||
executorService.shutdown()
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
import java.io.Closeable
|
||||
|
||||
import java.io.Closeable
|
||||
|
||||
import java.io.Closeable
|
||||
|
||||
class MyException(message: String) : Exception(message)
|
||||
|
||||
class Holder(var value: String) {
|
||||
public fun plusAssign(s: String?) {
|
||||
value += s
|
||||
if (s != "closed") {
|
||||
value += "->"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestLocal() : Closeable {
|
||||
|
||||
var status = Holder("")
|
||||
|
||||
private fun underMutexFun() {
|
||||
status += "called"
|
||||
}
|
||||
|
||||
fun local(): Holder {
|
||||
use {
|
||||
underMutexFun()
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
|
||||
fun nonLocalSimple(): Holder {
|
||||
use {
|
||||
underMutexFun()
|
||||
return status
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
fun nonLocalWithException(): Holder {
|
||||
use {
|
||||
try {
|
||||
underMutexFun()
|
||||
throw MyException("exception")
|
||||
} catch (e: MyException) {
|
||||
status += e.getMessage()!!
|
||||
return status
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
fun nonLocalWithFinally(): Holder {
|
||||
use {
|
||||
try {
|
||||
underMutexFun()
|
||||
return Holder("fail")
|
||||
} finally {
|
||||
status += "finally"
|
||||
return status
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
fun nonLocalWithExceptionAndFinally(): Holder {
|
||||
use {
|
||||
try {
|
||||
underMutexFun()
|
||||
throw MyException("exception")
|
||||
} catch (e: MyException) {
|
||||
status += e.getMessage()
|
||||
return status
|
||||
} finally {
|
||||
status += "finally"
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
fun nonLocalWithExceptionAndFinallyWithReturn(): Holder {
|
||||
use {
|
||||
try {
|
||||
underMutexFun()
|
||||
throw MyException("exception")
|
||||
} catch (e: MyException) {
|
||||
status += e.getMessage()
|
||||
return Holder("fail")
|
||||
} finally {
|
||||
status += "finally"
|
||||
return status
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
fun nonLocalNestedWithException(): Holder {
|
||||
use {
|
||||
try {
|
||||
try {
|
||||
underMutexFun()
|
||||
throw MyException("exception")
|
||||
} catch (e: MyException) {
|
||||
status += "exception"
|
||||
return Holder("fail")
|
||||
} finally {
|
||||
status += "finally1"
|
||||
return status
|
||||
}
|
||||
} finally {
|
||||
status += "finally2"
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
fun nonLocalNestedFinally(): Holder {
|
||||
use {
|
||||
try {
|
||||
try {
|
||||
underMutexFun()
|
||||
return status
|
||||
} finally {
|
||||
status += "finally1"
|
||||
status
|
||||
}
|
||||
} finally {
|
||||
status += "finally2"
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
status += "closed"
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
var callable = TestLocal()
|
||||
var result = callable.local()
|
||||
if (result.value != "called->closed") return "fail local: " + result.value
|
||||
|
||||
callable = TestLocal()
|
||||
result = callable.nonLocalSimple()
|
||||
if (result.value != "called->closed") return "fail nonLocalSimple: " + result.value
|
||||
|
||||
callable = TestLocal()
|
||||
result = callable.nonLocalWithException()
|
||||
if (result.value != "called->exception->closed") return "fail nonLocalWithException: " + result.value
|
||||
|
||||
callable = TestLocal()
|
||||
result = callable.nonLocalWithFinally()
|
||||
if (result.value != "called->finally->closed") return "fail nonLocalWithFinally: " + result.value
|
||||
|
||||
callable = TestLocal()
|
||||
result = callable.nonLocalWithExceptionAndFinally()
|
||||
if (result.value != "called->exception->finally->closed") return "fail nonLocalWithExceptionAndFinally: " + result.value
|
||||
|
||||
callable = TestLocal()
|
||||
result = callable.nonLocalWithExceptionAndFinallyWithReturn()
|
||||
if (result.value != "called->exception->finally->closed") return "fail nonLocalWithExceptionAndFinallyWithReturn: " + result.value
|
||||
|
||||
callable = TestLocal()
|
||||
result = callable.nonLocalNestedWithException()
|
||||
if (result.value != "called->exception->finally1->finally2->closed") return "fail nonLocalNestedWithException: " + result.value
|
||||
|
||||
callable = TestLocal()
|
||||
result = callable.nonLocalNestedFinally()
|
||||
if (result.value != "called->finally1->finally2->closed") return "fail nonLocalNestedFinally: " + result.value
|
||||
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
import java.io.Closeable
|
||||
|
||||
import java.io.Closeable
|
||||
|
||||
import java.io.Closeable
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class MyException(message: String) : Exception(message)
|
||||
|
||||
class Holder(var value: String) {
|
||||
public fun plusAssign(s: String?) {
|
||||
value += s
|
||||
if (s != "closed") {
|
||||
value += "->"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestLocal() : Closeable {
|
||||
|
||||
var status = Holder("")
|
||||
|
||||
private fun underMutexFun() {
|
||||
status += "called"
|
||||
}
|
||||
|
||||
fun local(): Holder {
|
||||
use {
|
||||
underMutexFun()
|
||||
}
|
||||
return status
|
||||
}
|
||||
|
||||
|
||||
fun nonLocalSimple(): Holder {
|
||||
use {
|
||||
underMutexFun()
|
||||
return status
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
fun nonLocalWithException(): Holder {
|
||||
use {
|
||||
try {
|
||||
underMutexFun()
|
||||
throw MyException("exception")
|
||||
} catch (e: MyException) {
|
||||
status += e.getMessage()!!
|
||||
return status
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
fun nonLocalWithFinally(): Holder {
|
||||
use {
|
||||
try {
|
||||
underMutexFun()
|
||||
return Holder("fail")
|
||||
} finally {
|
||||
status += "finally"
|
||||
return status
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
fun nonLocalWithExceptionAndFinally(): Holder {
|
||||
use {
|
||||
try {
|
||||
underMutexFun()
|
||||
throw MyException("exception")
|
||||
} catch (e: MyException) {
|
||||
status += e.getMessage()
|
||||
return status
|
||||
} finally {
|
||||
status += "finally"
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
fun nonLocalWithExceptionAndFinallyWithReturn(): Holder {
|
||||
use {
|
||||
try {
|
||||
underMutexFun()
|
||||
throw MyException("exception")
|
||||
} catch (e: MyException) {
|
||||
status += e.getMessage()
|
||||
return Holder("fail")
|
||||
} finally {
|
||||
status += "finally"
|
||||
return status
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
fun nonLocalNestedWithException(): Holder {
|
||||
use {
|
||||
try {
|
||||
try {
|
||||
underMutexFun()
|
||||
throw MyException("exception")
|
||||
} catch (e: MyException) {
|
||||
status += "exception"
|
||||
return Holder("fail")
|
||||
} finally {
|
||||
status += "finally1"
|
||||
return status
|
||||
}
|
||||
} finally {
|
||||
status += "finally2"
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
fun nonLocalNestedFinally(): Holder {
|
||||
use {
|
||||
try {
|
||||
try {
|
||||
underMutexFun()
|
||||
return status
|
||||
} finally {
|
||||
status += "finally1"
|
||||
status
|
||||
}
|
||||
} finally {
|
||||
status += "finally2"
|
||||
}
|
||||
}
|
||||
return Holder("fail")
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
status += "closed"
|
||||
throw MyException("error")
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
assertError(1,"called->closed") {
|
||||
local()
|
||||
}
|
||||
|
||||
assertError(2, "called->closed") {
|
||||
nonLocalSimple()
|
||||
}
|
||||
|
||||
assertError(3, "called->exception->closed") {
|
||||
nonLocalWithException()
|
||||
}
|
||||
|
||||
assertError(4, "called->finally->closed") {
|
||||
nonLocalWithFinally()
|
||||
}
|
||||
|
||||
assertError(5, "called->exception->finally->closed") {
|
||||
nonLocalWithExceptionAndFinally()
|
||||
}
|
||||
|
||||
assertError(6, "called->exception->finally->closed") {
|
||||
nonLocalWithExceptionAndFinallyWithReturn()
|
||||
}
|
||||
|
||||
assertError(7, "called->exception->finally1->finally2->closed") {
|
||||
nonLocalNestedWithException()
|
||||
}
|
||||
|
||||
assertError(8, "called->finally1->finally2->closed") {
|
||||
nonLocalNestedFinally()
|
||||
}
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
public fun assertError(index: Int, expected: String, l: TestLocal.()->Unit) {
|
||||
val testLocal = TestLocal()
|
||||
try {
|
||||
testLocal.l()
|
||||
fail("fail $index: no error")
|
||||
} catch (e: Exception) {
|
||||
assertEquals(expected, testLocal.status.value, "failed on $index")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user