[Wasm] PL tests implementation for Wasm target

Fixed #KT-58088
This commit is contained in:
Igor Yakovlev
2024-03-06 12:27:37 +01:00
committed by Space Team
parent 6b66195afc
commit 7c16528560
27 changed files with 900 additions and 37 deletions
@@ -27,6 +27,7 @@ private typealias Block<T> = () -> T
data class TestMode(
val isJs: Boolean = false,
val isNative: Boolean = false,
val isWasm: Boolean = false,
val staticCache: Scope = Scope.NOWHERE,
val lazyIr: Scope = Scope.NOWHERE
) {
@@ -39,7 +40,7 @@ data class TestMode(
}
init {
check(isJs xor isNative)
check(isJs xor isNative xor isWasm)
check(isNative || staticCache.notUsed)
check(isNative || lazyIr.notUsed)
}
@@ -159,10 +159,12 @@ fun box() = abiTest {
expectFailure(linkage("Function 'getAnnotationClassWithParameterOfParameterThatDisappearsInline' can not be called: Function uses unlinked class symbol '/AnnotationClassThatDisappears' (via annotation class 'AnnotationClassWithParameterOfParameterThatDisappears')")) { getAnnotationClassWithParameterOfParameterThatDisappearsInline() }
expectFailure(linkage("Constructor 'AnnotationClassThatDisappears.<init>' can not be called: No constructor found for symbol '/AnnotationClassThatDisappears.<init>'")) { getAnnotationClassWithParameterThatDisappearsAsAny() }
expectFailure(linkage("Constructor 'AnnotationClassThatDisappears.<init>' can not be called: No constructor found for symbol '/AnnotationClassThatDisappears.<init>'")) { getAnnotationClassWithParameterThatDisappearsAsAnyInline() }
expectSuccess("@AnnotationClassWithRenamedParameters(xi=129, xs=Banana)") { getAnnotationClassWithRenamedParameters().toString() }
expectSuccess("@AnnotationClassWithRenamedParameters(xi=130, xs=Pear)") { getAnnotationClassWithRenamedParametersInline().toString() }
expectSuccess("@AnnotationClassWithRenamedParameters(xi=131, xs=Orange)") { getAnnotationClassWithRenamedParametersAsAny().toString() }
expectSuccess("@AnnotationClassWithRenamedParameters(xi=132, xs=Peach)") { getAnnotationClassWithRenamedParametersAsAnyInline().toString() }
if (!testMode.isWasm) { //toString for annotation classes are not supported KT-66385
expectSuccess("@AnnotationClassWithRenamedParameters(xi=129, xs=Banana)") { getAnnotationClassWithRenamedParameters().toString() }
expectSuccess("@AnnotationClassWithRenamedParameters(xi=130, xs=Pear)") { getAnnotationClassWithRenamedParametersInline().toString() }
expectSuccess("@AnnotationClassWithRenamedParameters(xi=131, xs=Orange)") { getAnnotationClassWithRenamedParametersAsAny().toString() }
expectSuccess("@AnnotationClassWithRenamedParameters(xi=132, xs=Peach)") { getAnnotationClassWithRenamedParametersAsAnyInline().toString() }
}
expectFailure(linkage("Constructor 'AnnotationClassWithReorderedParameters.<init>' can not be called: No constructor found for symbol '/AnnotationClassWithReorderedParameters.<init>'")) { getAnnotationClassWithReorderedParameters() }
expectFailure(linkage("Constructor 'AnnotationClassWithReorderedParameters.<init>' can not be called: No constructor found for symbol '/AnnotationClassWithReorderedParameters.<init>'")) { getAnnotationClassWithReorderedParametersInline() }
expectFailure(linkage("Constructor 'AnnotationClassWithReorderedParameters.<init>' can not be called: No constructor found for symbol '/AnnotationClassWithReorderedParameters.<init>'")) { getAnnotationClassWithReorderedParametersAsAny() }
@@ -6,13 +6,6 @@ external class ExternalClassInheritedFromAbstractExternalClass : AbstractExterna
fun ExternalClassInheritedFromAbstractExternalClass.callRemovedFunction() = removedFunction()
class RegularClassInheritedFromAbstractExternalClass : AbstractExternalClass() {
override fun abstractFunction() = "RegularClassInheritedFromAbstractExternalClass.abstractFunction"
override fun removedAbstractFunction() = "RegularClassInheritedFromAbstractExternalClass.removedAbstractFunction"
}
fun RegularClassInheritedFromAbstractExternalClass.callRemovedFunction() = removedFunction()
open external class OpenExternalClass {
fun function(): String
}
@@ -24,15 +17,4 @@ external interface ExternalInterfaceInheritedFromOpenExternalClass : OpenExterna
external class ExternalClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass : ExternalInterfaceInheritedFromOpenExternalClass {
override fun abstractFunction(): String
}
class RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass :
ExternalInterfaceInheritedFromOpenExternalClass,
/* Note: Have to explicitly inherit from 'OpenExternalClass' becase otherwise JS codegen sees that
* class 'RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass' is inherited only from
* interface 'ExternalInterfaceInheritedFromOpenExternalClass' and does not figure out that a bridge has to be
* generated for function 'function' inherited from 'OpenExternalClass'.
*/
OpenExternalClass() {
override fun abstractFunction(): String = "RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass.abstractFunction"
}
}
@@ -3,28 +3,23 @@ import abitestutils.TestBuilder
fun box() = abiTest {
val ecifaec = ExternalClassInheritedFromAbstractExternalClass()
val rcifaec = RegularClassInheritedFromAbstractExternalClass()
val ecifeiifoec = ExternalClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass()
val rcifeiifoec = RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass()
expectSuccess("ExternalClassInheritedFromAbstractExternalClass.abstractFunction") { ecifaec.abstractFunction() }
expectSuccess("ExternalClassInheritedFromAbstractExternalClass.removedAbstractFunction") { ecifaec.removedAbstractFunction() }
expectRuntimeFailure("Calling abstract function AbstractExternalClass.addedAbstractFunction") { ecifaec.addedAbstractFunction() }
val expectedExceptionMessage = when (testMode.isWasm) {
true -> "Exception was thrown while running JavaScript code"
else -> "Calling abstract function AbstractExternalClass.addedAbstractFunction"
}
expectRuntimeFailure(expectedExceptionMessage) { ecifaec.addedAbstractFunction() }
expectSuccess("AbstractExternalClass.function") { ecifaec.function() }
expectFailure(linkage("Function 'removedFunction' can not be called: No function found for symbol '/ExternalClassInheritedFromAbstractExternalClass.removedFunction'")) { ecifaec.callRemovedFunction() }
expectSuccess("AbstractExternalClass.addedFunction") { ecifaec.addedFunction() }
expectSuccess("RegularClassInheritedFromAbstractExternalClass.abstractFunction") { rcifaec.abstractFunction() }
expectSuccess("RegularClassInheritedFromAbstractExternalClass.removedAbstractFunction") { rcifaec.removedAbstractFunction() }
expectFailure(nonImplementedCallable("function 'addedAbstractFunction'", "class 'RegularClassInheritedFromAbstractExternalClass'")) { rcifaec.addedAbstractFunction() }
expectSuccess("AbstractExternalClass.function") { rcifaec.function() }
expectFailure(linkage("Function 'removedFunction' can not be called: No function found for symbol '/RegularClassInheritedFromAbstractExternalClass.removedFunction'")) { rcifaec.callRemovedFunction() }
expectSuccess("AbstractExternalClass.addedFunction") { rcifaec.addedFunction() }
expectSuccess("OpenExternalClass.function") { ecifeiifoec.function() }
expectSuccess("ExternalClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass.abstractFunction") { ecifeiifoec.abstractFunction() }
expectSuccess("OpenExternalClass.function") { rcifeiifoec.function() }
expectSuccess("RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass.abstractFunction") { rcifeiifoec.abstractFunction() }
}
private fun TestBuilder.expectRuntimeFailure(errorMessage: String, block: () -> Any) =
@@ -0,0 +1,19 @@
function AbstractExternalClass() {}
AbstractExternalClass.prototype.abstractFunction = function() {
throw new Error("Calling abstract function AbstractExternalClass.abstractFunction");
}
AbstractExternalClass.prototype.removedAbstractFunction = function() {
throw new Error("Calling abstract function AbstractExternalClass.removedAbstractFunction");
}
// AbstractExternalClass.prototype.addedAbstractFunction = function() {
// throw new Error("Calling abstract function AbstractExternalClass.addedAbstractFunction");
// }
AbstractExternalClass.prototype.function = function() {
return "AbstractExternalClass.function";
}
AbstractExternalClass.prototype.removedFunction = function() {
return "AbstractExternalClass.removedFunction";
}
// AbstractExternalClass.prototype.addedFunction = function() {
// return "AbstractExternalClass.addedFunction";
// }
@@ -0,0 +1,19 @@
function AbstractExternalClass() {}
AbstractExternalClass.prototype.abstractFunction = function() {
throw new Error("Calling abstract function AbstractExternalClass.abstractFunction");
}
// AbstractExternalClass.prototype.removedAbstractFunction = function() {
// throw new Error("Calling abstract function AbstractExternalClass.removedAbstractFunction");
// }
AbstractExternalClass.prototype.addedAbstractFunction = function() {
throw new Error("Calling abstract function AbstractExternalClass.addedAbstractFunction");
}
AbstractExternalClass.prototype.function = function() {
return "AbstractExternalClass.function";
}
// AbstractExternalClass.prototype.removedFunction = function() {
// return "AbstractExternalClass.removedFunction";
// }
AbstractExternalClass.prototype.addedFunction = function() {
return "AbstractExternalClass.addedFunction";
}
@@ -0,0 +1,9 @@
abstract external class AbstractExternalClass {
abstract fun abstractFunction(): String
abstract fun removedAbstractFunction(): String
// abstract fun addedAbstractFunction(): String
fun function(): String
fun removedFunction(): String
// fun addedFunction(): String
}
@@ -0,0 +1,9 @@
abstract external class AbstractExternalClass {
abstract fun abstractFunction(): String
// abstract fun removedAbstractFunction(): String
abstract fun addedAbstractFunction(): String
fun function(): String
// fun removedFunction(): String
fun addedFunction(): String
}
@@ -0,0 +1,7 @@
STEP 0:
dependencies: stdlib
STEP 1:
dependencies: stdlib
modifications:
U : l1.kt.1 -> l1.kt
U : l1.js.1 -> l1.js
@@ -0,0 +1,10 @@
function OpenExternalClass() {}
OpenExternalClass.prototype.function = function() {
return "OpenExternalClass.function"
}
function ExternalInterfaceInheritedFromOpenExternalClass() {}
ExternalInterfaceInheritedFromOpenExternalClass.prototype = Object.create(OpenExternalClass.prototype);
ExternalInterfaceInheritedFromOpenExternalClass.prototype.abstractFunction = function() {
throw new Error("Calling abstract function ExternalInterfaceInheritedFromOpenExternalClass.abstractFunction");
}
@@ -0,0 +1,26 @@
class RegularClassInheritedFromAbstractExternalClass : AbstractExternalClass() {
override fun abstractFunction() = "RegularClassInheritedFromAbstractExternalClass.abstractFunction"
override fun removedAbstractFunction() = "RegularClassInheritedFromAbstractExternalClass.removedAbstractFunction"
}
fun RegularClassInheritedFromAbstractExternalClass.callRemovedFunction() = removedFunction()
open external class OpenExternalClass {
fun function(): String
}
@Suppress("INTERFACE_WITH_SUPERCLASS")
external interface ExternalInterfaceInheritedFromOpenExternalClass : OpenExternalClass {
fun abstractFunction(): String
}
class RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass :
ExternalInterfaceInheritedFromOpenExternalClass,
/* Note: Have to explicitly inherit from 'OpenExternalClass' becase otherwise JS codegen sees that
* class 'RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass' is inherited only from
* interface 'ExternalInterfaceInheritedFromOpenExternalClass' and does not figure out that a bridge has to be
* generated for function 'function' inherited from 'OpenExternalClass'.
*/
OpenExternalClass() {
override fun abstractFunction(): String = "RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass.abstractFunction"
}
@@ -0,0 +1,2 @@
STEP 0:
dependencies: stdlib, lib1
@@ -0,0 +1,20 @@
import abitestutils.abiTest
import abitestutils.TestBuilder
fun box() = abiTest {
val rcifaec = RegularClassInheritedFromAbstractExternalClass()
val rcifeiifoec = RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass()
expectSuccess("RegularClassInheritedFromAbstractExternalClass.abstractFunction") { rcifaec.abstractFunction() }
expectSuccess("RegularClassInheritedFromAbstractExternalClass.removedAbstractFunction") { rcifaec.removedAbstractFunction() }
expectFailure(nonImplementedCallable("function 'addedAbstractFunction'", "class 'RegularClassInheritedFromAbstractExternalClass'")) { rcifaec.addedAbstractFunction() }
expectSuccess("AbstractExternalClass.function") { rcifaec.function() }
expectFailure(linkage("Function 'removedFunction' can not be called: No function found for symbol '/RegularClassInheritedFromAbstractExternalClass.removedFunction'")) { rcifaec.callRemovedFunction() }
expectSuccess("AbstractExternalClass.addedFunction") { rcifaec.addedFunction() }
expectSuccess("OpenExternalClass.function") { rcifeiifoec.function() }
expectSuccess("RegularClassInheritedFromExternalInterfaceInheritedFromOpenExternalClass.abstractFunction") { rcifeiifoec.abstractFunction() }
}
private fun TestBuilder.expectRuntimeFailure(errorMessage: String, block: () -> Any) =
expectFailure(custom { throwable -> throwable !is Exception && throwable.message == errorMessage }) { block() }
@@ -0,0 +1,2 @@
STEP 1:
dependencies: stdlib, lib1, lib2
@@ -0,0 +1,7 @@
MODULES: lib1, lib2, main
STEP 0:
libs: lib1, lib2
STEP 1:
libs: lib1, main