Add few tests for contracts

- Contracts in getter/setter (unexpected behaviour)
- Check smartcasts when non-null assertion for a contract function is used
- Check work of contracts when type parameter of the callsInPlace is specify explicitly
- Check smartcasts working if type checking for contract function is used
This commit is contained in:
victor.petukhov
2018-09-25 12:21:42 +03:00
parent ecb3f10e47
commit 8538866778
9 changed files with 484 additions and 5 deletions
@@ -0,0 +1,52 @@
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
/*
KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE)
SECTION: contracts
CATEGORIES: analysis, controlFlow, initialization
NUMBER: 7
DESCRIPTION: Check initialization when type parameter of the callsInPlace is specify explicitly.
*/
// FILE: contracts.kt
package contracts
import kotlin.contracts.*
inline fun <T> case_1(block: () -> T): T {
contract {
callsInPlace<T>(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
inline fun case_2(block: () -> Int): Int {
contract {
callsInPlace<Number>(block, InvocationKind.EXACTLY_ONCE)
}
return block()
}
// FILE: usages.kt
import contracts.*
fun case_1() {
val value_1: Int
case_1 {
value_1 = 10
}
println(value_1)
}
fun case_2() {
val value_1: Int
case_2 {
value_1 = 10
10
}
println(value_1)
}
@@ -0,0 +1,13 @@
package
public fun case_1(): kotlin.Unit
public fun case_2(): kotlin.Unit
package contracts {
public inline fun </*0*/ T> case_1(/*0*/ block: () -> T): T
CallsInPlace(block, EXACTLY_ONCE)
public inline fun case_2(/*0*/ block: () -> kotlin.Int): kotlin.Int
CallsInPlace(block, EXACTLY_ONCE)
}
@@ -0,0 +1,58 @@
// !LANGUAGE: +AllowContractsForCustomFunctions +UseReturnsEffect
// !WITH_CONTRACT_FUNCTIONS
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
/*
KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE)
SECTION: contracts
CATEGORIES: analysis, smartcasts
NUMBER: 15
DESCRIPTION: Check smartcasts working if type checking for contract function is used
UNEXPECTED BEHAVIOUR
ISSUES: KT-27241
*/
// FILE: contracts.kt
package contracts
import kotlin.contracts.*
fun case_1_1(cond: Boolean): Any {
contract { returns(true) implies cond }
return cond
}
fun case_1_2(value: Any): Boolean {
contract { returns(true) implies (value is Boolean) }
return value is Boolean
}
fun case_2(cond: Boolean): Any {
contract { returns(true) implies cond }
return cond
}
// FILE: usages.kt
import contracts.*
fun case_1(value: Any) {
if (contracts.case_1_2(contracts.case_1_1(value is Char))) {
println(<!DEBUG_INFO_SMARTCAST!>value<!>.category)
}
}
fun case_2(value: Any) {
if (contracts.case_2(value is Char) is Boolean) {
println(<!DEBUG_INFO_SMARTCAST!>value<!>.category)
}
}
fun case_3(value: String?) {
if (<!USELESS_IS_CHECK!>!value.isNullOrEmpty() is Boolean<!>) {
<!DEBUG_INFO_SMARTCAST!>value<!>.length
}
}
@@ -0,0 +1,124 @@
package
public fun case_1(/*0*/ value: kotlin.Any): kotlin.Unit
public fun case_2(/*0*/ value: kotlin.Any): kotlin.Unit
public fun case_3(/*0*/ value: kotlin.String?): kotlin.Unit
public inline fun </*0*/ T> funWithAtLeastOnceCallsInPlace(/*0*/ block: () -> T): T
CallsInPlace(block, AT_LEAST_ONCE)
public inline fun funWithAtLeastOnceCallsInPlace(/*0*/ block: () -> kotlin.Unit): kotlin.Unit
CallsInPlace(block, AT_LEAST_ONCE)
public inline fun funWithAtMostOnceCallsInPlace(/*0*/ block: () -> kotlin.Unit): kotlin.Unit
CallsInPlace(block, AT_MOST_ONCE)
public inline fun </*0*/ T> funWithExactlyOnceCallsInPlace(/*0*/ block: () -> T): T
CallsInPlace(block, EXACTLY_ONCE)
public inline fun funWithExactlyOnceCallsInPlace(/*0*/ block: () -> kotlin.Unit): kotlin.Unit
CallsInPlace(block, EXACTLY_ONCE)
public fun funWithReturns(/*0*/ cond: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> cond
public fun funWithReturnsAndInvertCondition(/*0*/ cond: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> !cond
public fun funWithReturnsAndInvertTypeCheck(/*0*/ value_1: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> value_1 !is String
public fun funWithReturnsAndNotNullCheck(/*0*/ value_1: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> value_1 != null
public fun funWithReturnsAndNullCheck(/*0*/ value_1: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> value_1 == null
public fun funWithReturnsAndTypeCheck(/*0*/ value_1: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> value_1 is String
public fun funWithReturnsFalse(/*0*/ cond: kotlin.Boolean): kotlin.Boolean
Returns(FALSE) -> cond
public fun funWithReturnsFalseAndInvertCondition(/*0*/ cond: kotlin.Boolean): kotlin.Boolean
Returns(FALSE) -> !cond
public fun funWithReturnsFalseAndInvertTypeCheck(/*0*/ value_1: kotlin.Any?): kotlin.Boolean
Returns(FALSE) -> value_1 !is String
public fun funWithReturnsFalseAndNotNullCheck(/*0*/ value_1: kotlin.Number?): kotlin.Boolean
Returns(FALSE) -> value_1 != null
public fun funWithReturnsFalseAndNullCheck(/*0*/ value_1: kotlin.Number?): kotlin.Boolean
Returns(FALSE) -> value_1 == null
public fun funWithReturnsFalseAndTypeCheck(/*0*/ value_1: kotlin.Any?): kotlin.Boolean
Returns(FALSE) -> value_1 is String
public fun funWithReturnsNotNull(/*0*/ cond: kotlin.Boolean): kotlin.Boolean?
Returns(NOT_NULL) -> cond
public fun funWithReturnsNotNullAndInvertCondition(/*0*/ cond: kotlin.Boolean): kotlin.Boolean?
Returns(NOT_NULL) -> !cond
public fun funWithReturnsNotNullAndInvertTypeCheck(/*0*/ value_1: kotlin.Any?): kotlin.Boolean?
Returns(NOT_NULL) -> value_1 !is String
public fun funWithReturnsNotNullAndNotNullCheck(/*0*/ value_1: kotlin.Number?): kotlin.Boolean?
Returns(NOT_NULL) -> value_1 != null
public fun funWithReturnsNotNullAndNullCheck(/*0*/ value_1: kotlin.Number?): kotlin.Boolean?
Returns(NOT_NULL) -> value_1 == null
public fun funWithReturnsNotNullAndTypeCheck(/*0*/ value_1: kotlin.Any?): kotlin.Boolean?
Returns(NOT_NULL) -> value_1 is String
public fun funWithReturnsNull(/*0*/ cond: kotlin.Boolean): kotlin.Boolean?
Returns(NULL) -> cond
public fun funWithReturnsNullAndInvertCondition(/*0*/ cond: kotlin.Boolean): kotlin.Boolean?
Returns(NULL) -> !cond
public fun funWithReturnsNullAndInvertTypeCheck(/*0*/ value_1: kotlin.Any?): kotlin.Boolean?
Returns(NULL) -> value_1 !is String
public fun funWithReturnsNullAndNotNullCheck(/*0*/ value_1: kotlin.Number?): kotlin.Boolean?
Returns(NULL) -> value_1 != null
public fun funWithReturnsNullAndNullCheck(/*0*/ value_1: kotlin.Number?): kotlin.Boolean?
Returns(NULL) -> value_1 == null
public fun funWithReturnsNullAndTypeCheck(/*0*/ value_1: kotlin.Any?): kotlin.Boolean?
Returns(NULL) -> value_1 is String
public fun funWithReturnsTrue(/*0*/ cond: kotlin.Boolean): kotlin.Boolean
Returns(TRUE) -> cond
public fun funWithReturnsTrueAndInvertCondition(/*0*/ cond: kotlin.Boolean): kotlin.Boolean
Returns(TRUE) -> !cond
public fun funWithReturnsTrueAndInvertTypeCheck(/*0*/ value_1: kotlin.Any?): kotlin.Boolean
Returns(TRUE) -> value_1 !is String
public fun funWithReturnsTrueAndNotNullCheck(/*0*/ value_1: kotlin.Any?): kotlin.Boolean
Returns(TRUE) -> value_1 != null
public fun funWithReturnsTrueAndNullCheck(/*0*/ value_1: kotlin.Any?): kotlin.Boolean
Returns(TRUE) -> value_1 == null
public fun funWithReturnsTrueAndTypeCheck(/*0*/ value_1: kotlin.Any?): kotlin.Boolean
Returns(TRUE) -> value_1 is String
public inline fun funWithUnknownCallsInPlace(/*0*/ block: () -> kotlin.Unit): kotlin.Unit
CallsInPlace(block, UNKNOWN)
package contracts {
public fun case_1_1(/*0*/ cond: kotlin.Boolean): kotlin.Any
Returns(TRUE) -> cond
public fun case_1_2(/*0*/ value: kotlin.Any): kotlin.Boolean
Returns(TRUE) -> value is Boolean
public fun case_2(/*0*/ cond: kotlin.Boolean): kotlin.Any
Returns(TRUE) -> cond
}
@@ -0,0 +1,80 @@
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
/*
KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (POSITIVE)
SECTION: contracts
CATEGORIES: analysis, smartcasts
NUMBER: 14
DESCRIPTION: Check smartcast with non-null assertion for a contract function.
UNEXPECTED BEHAVIOUR
ISSUES: KT-26856
*/
// FILE: contracts.kt
package contracts
import kotlin.contracts.*
fun case_1(value_1: Int?): Boolean? {
contract {
returns(true) implies (value_1 != null)
}
return value_1 != null
}
fun case_2(value_1: Int?): Boolean {
contract {
returns(false) implies (value_1 != null)
}
return value_1 != null
}
fun case_3(value_1: Int?): Boolean? {
contract {
returnsNotNull() implies (value_1 != null)
}
return value_1 != null
}
fun case_4(value_1: Any?): Boolean {
contract {
returnsNotNull() implies (value_1 is Number)
}
return value_1 is Number
}
// FILE: usages.kt
import contracts.*
fun case_1(value_1: Int?) {
if (contracts.case_1(value_1)!!) {
value_1<!UNSAFE_CALL!>.<!>inv()
}
}
fun case_2(value_1: Int?) {
if (!contracts.case_2(value_1)<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>) {
value_1<!UNSAFE_CALL!>.<!>inv()
}
}
fun case_3(value_1: Int?) {
if (contracts.case_3(value_1)!!) {
value_1<!UNSAFE_CALL!>.<!>inv()
}
}
fun case_4(value_1: Any?) {
if (<!SENSELESS_COMPARISON!>contracts.case_4(value_1) != null<!>) {
<!DEBUG_INFO_SMARTCAST!>value_1<!>.toByte()
}
}
@@ -0,0 +1,21 @@
package
public fun case_1(/*0*/ value_1: kotlin.Int?): kotlin.Unit
public fun case_2(/*0*/ value_1: kotlin.Int?): kotlin.Unit
public fun case_3(/*0*/ value_1: kotlin.Int?): kotlin.Unit
public fun case_4(/*0*/ value_1: kotlin.Any?): kotlin.Unit
package contracts {
public fun case_1(/*0*/ value_1: kotlin.Int?): kotlin.Boolean?
Returns(TRUE) -> value_1 != null
public fun case_2(/*0*/ value_1: kotlin.Int?): kotlin.Boolean
Returns(FALSE) -> value_1 != null
public fun case_3(/*0*/ value_1: kotlin.Int?): kotlin.Boolean?
Returns(NOT_NULL) -> value_1 != null
public fun case_4(/*0*/ value_1: kotlin.Any?): kotlin.Boolean
Returns(NOT_NULL) -> value_1 is Number
}
@@ -0,0 +1,64 @@
// !LANGUAGE: +AllowContractsForCustomFunctions +UseCallsInPlaceEffect
// !DIAGNOSTICS: -INVISIBLE_REFERENCE -INVISIBLE_MEMBER -UNUSED_PARAMETER
// !USE_EXPERIMENTAL: kotlin.contracts.ExperimentalContracts
/*
KOTLIN DIAGNOSTICS NOT LINKED SPEC TEST (NEGATIVE)
SECTION: contracts
CATEGORIES: declarations, contractFunction
NUMBER: 4
DESCRIPTION: Check that fun with contract and CallsInPlace effect is an inline function.
UNEXPECTED BEHAVIOUR
ISSUES: KT-27090
*/
import kotlin.contracts.*
val Boolean.case_1: () -> Unit
get() {
contract {
returns() implies (this@case_1)
}
return {}
}
val (() -> Unit).case_2: () -> Unit
get() {
contract {
callsInPlace(this@case_2, InvocationKind.EXACTLY_ONCE)
}
return {}
}
var Boolean.case_3: () -> Unit
get() {
return {}
}
set(value) {
contract {
callsInPlace(value, InvocationKind.EXACTLY_ONCE)
}
}
var (() -> Unit).case_4: () -> Unit
get() {
return {}
}
set(value) {
contract {
callsInPlace(this@case_4, InvocationKind.EXACTLY_ONCE)
}
}
val Boolean.case_5: () -> Unit
get() {
contract {
returns() implies (this@case_5)
}
if (!this@case_5)
throw Exception()
return {}
}
@@ -0,0 +1,7 @@
package
public val kotlin.Boolean.case_1: () -> kotlin.Unit
public val (() -> kotlin.Unit).case_2: () -> kotlin.Unit
public var kotlin.Boolean.case_3: () -> kotlin.Unit
public var (() -> kotlin.Unit).case_4: () -> kotlin.Unit
public val kotlin.Boolean.case_5: () -> kotlin.Unit
@@ -775,6 +775,16 @@ public class DiagnosticsTestSpecGenerated extends AbstractDiagnosticsTestSpec {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/5.kt");
}
@TestMetadata("6.kt")
public void test6() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/6.kt");
}
@TestMetadata("7.kt")
public void test7() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos/7.kt");
}
public void testAllFilesPresentInPos() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/controlFlow/initialization/pos"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@@ -906,6 +916,11 @@ public class DiagnosticsTestSpecGenerated extends AbstractDiagnosticsTestSpec {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/13.kt");
}
@TestMetadata("15.kt")
public void test15() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/15.kt");
}
@TestMetadata("2.kt")
public void test2() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/neg/2.kt");
@@ -974,6 +989,21 @@ public class DiagnosticsTestSpecGenerated extends AbstractDiagnosticsTestSpec {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/11.kt");
}
@TestMetadata("12.kt")
public void test12() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/12.kt");
}
@TestMetadata("13.kt")
public void test13() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/13.kt");
}
@TestMetadata("14.kt")
public void test14() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/14.kt");
}
@TestMetadata("2.kt")
public void test2() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/analysis/smartcasts/pos/2.kt");
@@ -1090,6 +1120,26 @@ public class DiagnosticsTestSpecGenerated extends AbstractDiagnosticsTestSpec {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/13.kt");
}
@TestMetadata("14.kt")
public void test14() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/14.kt");
}
@TestMetadata("15.kt")
public void test15() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/15.kt");
}
@TestMetadata("16.kt")
public void test16() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/16.kt");
}
@TestMetadata("17.kt")
public void test17() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/17.kt");
}
@TestMetadata("2.kt")
public void test2() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/2.kt");
@@ -1163,11 +1213,6 @@ public class DiagnosticsTestSpecGenerated extends AbstractDiagnosticsTestSpec {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/pos/4.kt");
}
@TestMetadata("5.kt")
public void test5() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/pos/5.kt");
}
public void testAllFilesPresentInPos() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/pos"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@@ -1211,6 +1256,11 @@ public class DiagnosticsTestSpecGenerated extends AbstractDiagnosticsTestSpec {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/callsInPlace/neg/1.kt");
}
@TestMetadata("2.kt")
public void test2() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/callsInPlace/neg/2.kt");
}
public void testAllFilesPresentInNeg() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/callsInPlace/neg"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@@ -1397,6 +1447,16 @@ public class DiagnosticsTestSpecGenerated extends AbstractDiagnosticsTestSpec {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/2.kt");
}
@TestMetadata("3.kt")
public void test3() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/3.kt");
}
@TestMetadata("4.kt")
public void test4() throws Exception {
runTest("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg/4.kt");
}
public void testAllFilesPresentInNeg() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractFunction/neg"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}