KT-9377 Support is-checks for read-only collections
Additional tests.
This commit is contained in:
@@ -102,5 +102,8 @@ fun box(): String {
|
||||
assert(mentry is MutableMap.MutableEntry<*, *>) { "MME should satisfy 'is MutableMap.MutableEntry'"}
|
||||
assert(hashMapEntry is MutableMap.MutableEntry<*, *>) { "HashMap.Entry should satisfy 'is MutableMap.MutableEntry'"}
|
||||
|
||||
assert((mlist as Any) !is MutableSet<*>) { "ML !is MutableSet" }
|
||||
assert((mlist as Any) !is MutableIterator<*>) { "ML !is MutableIterator" }
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -28,23 +28,23 @@ class MME : MutableMap.MutableEntry<String, String> {
|
||||
override fun setValue(value: String): String = throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
inline fun safeAsReturnsNull(operation: String, block: () -> Any?) {
|
||||
inline fun safeAsReturnsNull(operation: String, cast: () -> Any?) {
|
||||
try {
|
||||
val x = block()
|
||||
val x = cast()
|
||||
assert(x == null) { "$operation: should return null, got $x" }
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
assert(false) { "$operation: should not throw exceptions, got $e" }
|
||||
throw AssertionError("$operation: should not throw exceptions, got $e")
|
||||
}
|
||||
}
|
||||
|
||||
inline fun safeAsReturnsNonNull(operation: String, block: () -> Any?) {
|
||||
inline fun safeAsReturnsNonNull(operation: String, cast: () -> Any?) {
|
||||
try {
|
||||
val x = block()
|
||||
val x = cast()
|
||||
assert(x != null) { "$operation: should return non-null" }
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
assert(false) { "$operation: should not throw exceptions, got $e" }
|
||||
throw AssertionError("$operation: should not throw exceptions, got $e")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ fun box(): String {
|
||||
|
||||
safeAsReturnsNull("map as? MutableMap") { map as? MutableMap<*, *> }
|
||||
safeAsReturnsNonNull("mmap as? MutableMap") { mmap as? MutableMap<*, *> }
|
||||
safeAsReturnsNonNull("hashMap as? MutableMap") { hashMap as? MutableMap<*, *> }
|
||||
|
||||
val entry = ME() as Any
|
||||
val mentry = MME()
|
||||
@@ -129,5 +130,8 @@ fun box(): String {
|
||||
safeAsReturnsNull("null as? MutableMap") { null as? MutableMap<*, *> }
|
||||
safeAsReturnsNull("null as? MutableMap.MutableEntry") { null as? MutableMap.MutableEntry<*, *> }
|
||||
|
||||
safeAsReturnsNull("mlist as? MutableSet") { mlist as? MutableSet<*> }
|
||||
safeAsReturnsNull("mlist as? MutableIterator") { mlist as? MutableIterator<*> }
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
fun unsupported(): Nothing = throw UnsupportedOperationException()
|
||||
|
||||
class Weird : Iterator<String>, MutableIterable<String>, MutableMap.MutableEntry<String, String> {
|
||||
override fun next(): String = unsupported()
|
||||
override fun hasNext(): Boolean = unsupported()
|
||||
override fun getKey(): String = unsupported()
|
||||
override fun getValue(): String = unsupported()
|
||||
override fun setValue(value: String): String = unsupported()
|
||||
override fun iterator(): MutableIterator<String> = unsupported()
|
||||
}
|
||||
|
||||
inline fun asFailsWithCCE(operation: String, cast: () -> Unit) {
|
||||
try {
|
||||
cast()
|
||||
}
|
||||
catch (e: java.lang.ClassCastException) {
|
||||
return
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
throw AssertionError("$operation: should throw ClassCastException, got $e")
|
||||
}
|
||||
throw AssertionError("$operation: should throw ClassCastException, no exception thrown")
|
||||
}
|
||||
|
||||
inline fun asSucceeds(operation: String, cast: () -> Unit) {
|
||||
try {
|
||||
cast()
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
throw AssertionError("$operation: should not throw exceptions, got $e")
|
||||
}
|
||||
}
|
||||
|
||||
inline fun safeAsReturnsNull(operation: String, cast: () -> Any?) {
|
||||
try {
|
||||
val x = cast()
|
||||
assert(x == null) { "$operation: should return null, got $x" }
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
throw AssertionError("$operation: should not throw exceptions, got $e")
|
||||
}
|
||||
}
|
||||
|
||||
inline fun safeAsReturnsNonNull(operation: String, cast: () -> Any?) {
|
||||
try {
|
||||
val x = cast()
|
||||
assert(x != null) { "$operation: should return non-null" }
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
throw AssertionError("$operation: should not throw exceptions, got $e")
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T> reifiedIs(x: Any): Boolean = x is T
|
||||
|
||||
inline fun <reified T> reifiedIsNot(x: Any): Boolean = x !is T
|
||||
|
||||
inline fun <reified T> reifiedAsSucceeds(x: Any, operation: String) {
|
||||
try {
|
||||
x as T
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
throw AssertionError("$operation: should not throw exceptions, got $e")
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T> reifiedAsFailsWithCCE(x: Any, operation: String) {
|
||||
try {
|
||||
x as T
|
||||
}
|
||||
catch (e: java.lang.ClassCastException) {
|
||||
return
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
throw AssertionError("$operation: should throw ClassCastException, got $e")
|
||||
}
|
||||
throw AssertionError("$operation: should fail with CCE, no exception thrown")
|
||||
}
|
||||
|
||||
inline fun <reified T> reifiedSafeAsReturnsNonNull(x: Any?, operation: String) {
|
||||
val y = try {
|
||||
x as? T
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
throw AssertionError("$operation: should not throw exceptions, got $e")
|
||||
}
|
||||
if (y == null) {
|
||||
throw AssertionError("$operation: should return non-null, got null")
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified T> reifiedSafeAsReturnsNull(x: Any?, operation: String) {
|
||||
val y = try {
|
||||
x as? T
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
throw AssertionError("$operation: should not throw exceptions, got $e")
|
||||
}
|
||||
if (y != null) {
|
||||
throw AssertionError("$operation: should return null, got $y")
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val w: Any = Weird()
|
||||
|
||||
assert(w is Iterator<*>) { "w is Iterator<*>" }
|
||||
assert(w !is MutableIterator<*>) { "w !is MutableIterator<*>" }
|
||||
assert(w is MutableIterable<*>) { "w is MutableIterable<*>" }
|
||||
assert(w is MutableMap.MutableEntry<*, *>) { "w is MutableMap.MutableEntry<*, *>" }
|
||||
|
||||
asSucceeds("w as Iterator<*>") { w as Iterator<*> }
|
||||
asFailsWithCCE("w as MutableIterator<*>") { w as MutableIterator<*> }
|
||||
asSucceeds("w as MutableIterable<*>") { w as MutableIterable<*> }
|
||||
asSucceeds("w as MutableMap.MutableEntry<*, *>") { w as MutableMap.MutableEntry<*, *> }
|
||||
|
||||
safeAsReturnsNonNull("w as Iterator<*>") { w as? Iterator<*> }
|
||||
safeAsReturnsNull("w as? MutableIterator<*>") { w as? MutableIterator<*> }
|
||||
safeAsReturnsNonNull("w as? MutableIterable<*>") { w as? MutableIterable<*> }
|
||||
safeAsReturnsNonNull("w as? MutableMap.MutableEntry<*, *>") { w as? MutableMap.MutableEntry<*, *> }
|
||||
|
||||
assert(reifiedIs<Iterator<*>>(w)) { "reifiedIs<Iterator<*>>(w)" }
|
||||
assert(reifiedIsNot<MutableIterator<*>>(w)) { "reifiedIsNot<MutableIterator<*>>(w)" }
|
||||
assert(reifiedIs<MutableIterable<*>>(w)) { "reifiedIs<MutableIterable<*>>(w)" }
|
||||
assert(reifiedIs<MutableMap.MutableEntry<*, *>>(w)) { "reifiedIs<MutableMap.MutableEntry<*, *>>(w)" }
|
||||
|
||||
reifiedAsSucceeds<Iterator<*>>(w, "reified w as Iterator<*>")
|
||||
reifiedAsFailsWithCCE<MutableIterator<*>>(w, "reified w as MutableIterator<*>")
|
||||
reifiedAsSucceeds<MutableIterable<*>>(w, "reified w as MutableIterable<*>")
|
||||
reifiedAsSucceeds<MutableMap.MutableEntry<*, *>>(w, "reified w as MutableMap.MutableEntry<*, *>")
|
||||
|
||||
reifiedSafeAsReturnsNonNull<Iterator<*>>(w, "reified w as? Iterator<*>")
|
||||
reifiedSafeAsReturnsNull<MutableIterator<*>>(w, "reified w as? MutableIterator<*>")
|
||||
reifiedSafeAsReturnsNonNull<MutableIterable<*>>(w, "reified w as? MutableIterable<*>")
|
||||
reifiedSafeAsReturnsNonNull<MutableMap.MutableEntry<*, *>>(w, "reified w as? MutableMap.MutableEntry<*, *>")
|
||||
|
||||
return "OK"
|
||||
}
|
||||
Reference in New Issue
Block a user