[K/N][Tests] Migrate framework and objcexport tests

^KT-61259
This commit is contained in:
Vladimir Sukharev
2024-01-22 20:12:14 +01:00
committed by Space Team
parent f00a145dd7
commit 025771460c
136 changed files with 698 additions and 416 deletions
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2021 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.
*/
public abstract class AbstractBase(val y: Int) {
abstract val x: Int
}
@@ -0,0 +1,18 @@
import Foundation
import AbstractInstantiation
func testInstantiate() throws {
// this is failure test, it shouldn't work
let base = AbstractBase(y: 5)
}
class AbstractInstantiationTests : TestProvider {
var tests: [TestCase] = []
init() {
providers.append(self)
tests = [
TestCase(name: "testInstantiate", method: withAutorelease(testInstantiate))
]
}
}
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2021 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 lib
fun lib() {}
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2021 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 main
fun main() {}
@@ -0,0 +1,17 @@
language=Objective-C
---
struct ForwardDeclaredStruct;
@class ForwardDeclaredClass;
@protocol ForwardDeclaredProtocol;
struct ForwardDeclaredStruct* sameStruct(struct ForwardDeclaredStruct* ptr) {
return ptr;
}
ForwardDeclaredClass* sameClass(ForwardDeclaredClass* obj) {
return obj;
}
id<ForwardDeclaredProtocol> sameProtocol(id<ForwardDeclaredProtocol> obj) {
return obj;
}
@@ -0,0 +1,10 @@
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import forwardDeclarations.*
import cnames.structs.ForwardDeclaredStruct
import objcnames.classes.ForwardDeclaredClass
import objcnames.protocols.ForwardDeclaredProtocolProtocol
import kotlinx.cinterop.CPointer
fun sameForwardDeclaredStruct(ptr: CPointer<ForwardDeclaredStruct>?): CPointer<ForwardDeclaredStruct>? = sameStruct(ptr)
fun sameForwardDeclaredClass(obj: ForwardDeclaredClass?): ForwardDeclaredClass? = sameClass(obj)
fun sameForwardDeclaredProtocol(obj: ForwardDeclaredProtocolProtocol?): ForwardDeclaredProtocolProtocol? = sameProtocol(obj)
@@ -0,0 +1,25 @@
import ForwardDeclarations
private func test1() throws {
let ptr = UnsafeMutableRawPointer(bitPattern: 0x1234)
try assertEquals(actual: ForwardDeclarationsKt.sameForwardDeclaredStruct(ptr: ptr), expected: ptr)
// We can't actually test this, because Swift can't import neither types nor functions due to
// "interface/protocol '...' is incomplete":
//
// let classObj: ForwardDeclaredClass? = nil
// try assertNil(LibKt.sameForwardDeclaredClass(obj: classObj))
//
// let protocolObj: ForwardDeclaredProtocol? = nil
// try assertNil(LibKt.sameForwardDeclaredProtocol(obj: protocolObj))
}
// -------- Execution of the test --------
class ForwardDeclarationsTests : SimpleTestProvider {
override init() {
super.init()
test("test1", test1)
}
}
@@ -0,0 +1,3 @@
language = Objective-C
headers = Foundation/NSArray.h Foundation/NSValue.h Foundation/NSString.h
headerFilter = gh3343.h Foundation/NSArray.h Foundation/NSValue.h Foundation/NSString.h
+11
View File
@@ -0,0 +1,11 @@
#import <Foundation/Foundation.h>
NSString* foo1(int x) {
return [NSString stringWithFormat:@"%d", x];
}
NSArray* foo2(int x) {
NSValue* xx = @(x);
NSString* s = @"zzz";
return [NSArray arrayWithObjects: xx, s, nil];
}
+16
View File
@@ -0,0 +1,16 @@
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kotlinx.cinterop.*
import gh3343.*
import kotlin.native.ref.*
fun run(): List<Any?> {
val result = mutableListOf<Any?>()
result.add(foo1(42))
val list = foo2(117)
if (list != null) {
result.add(list.size)
for (x in list)
result.add(x)
}
return result
}
@@ -0,0 +1,23 @@
import Foundation
import Gh3343
func testGh3343() throws {
let list = Gh3343Kt.run()
try assertEquals(actual: list[0] as? String, expected: "42")
try assertEquals(actual: list[1] as? Int, expected: 2)
try assertEquals(actual: list[2] as? Int, expected: 117)
try assertEquals(actual: list[3] as? String, expected: "zzz")
}
// -------- Execution of the test --------
class Gh3343Tests : TestProvider {
var tests: [TestCase] = []
init() {
providers.append(self)
tests = [
TestCase(name: "Gh3343", method: withAutorelease(testGh3343)),
]
}
}
@@ -0,0 +1,20 @@
@file:OptIn(kotlin.experimental.ExperimentalNativeApi::class)
import kotlin.native.Platform
// The following 2 singletons are unused. However, since we are generating ObjC bindings for them,
// they should be marked as used, so that the code generator emits their deinitialization.
object A {
fun foo() = 1
}
class B {
companion object {
fun foo() = 2
}
}
fun enableMemoryChecker() {
Platform.isMemoryLeakCheckerActive = true
}
@@ -0,0 +1,40 @@
import Kt42397
class Results {
var aFoo: Int32 = 0
var bFoo: Int32 = 0
}
func runTestKt42397(pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
autoreleasepool {
Kt42397Kt.enableMemoryChecker()
let results = pointer.bindMemory(to: Results.self, capacity: 1).pointee
results.aFoo = A().foo()
results.bFoo = B.Companion().foo()
}
return nil
}
func testKt42397() throws {
let results = Results()
let resultsPtr = UnsafeMutablePointer<Results>.allocate(capacity: 1)
resultsPtr.initialize(to: results)
var thread: pthread_t? = nil
let result = pthread_create(&thread, nil, runTestKt42397, resultsPtr)
try assertEquals(actual: result, expected: 0)
pthread_join(thread!, nil)
try assertEquals(actual: results.aFoo, expected: 1)
try assertEquals(actual: results.bFoo, expected: 2)
}
// -------- Execution of the test --------
class Kt42397Tests : SimpleTestProvider {
override init() {
super.init()
test("Kt42397", testKt42397)
}
}
@@ -0,0 +1,15 @@
---
enum E {
A, B, C
};
struct S {
int i;
float f;
};
struct S globalS = { .i = 3, .f = 3.14f };
enum E createEnum() {
return A;
}
@@ -0,0 +1,14 @@
@file:OptIn(kotlinx.cinterop.ExperimentalForeignApi::class)
import kt43517.*
fun produceEnum(): E =
createEnum()
fun compareEnums(e1: E, e2: E): Boolean =
e1 == e2
fun getFirstField(s: S): Int =
s.i
fun getGlobalS(): S =
globalS
@@ -0,0 +1,24 @@
import Foundation
import Kt43517
func testKt43517() throws {
try assertEquals(
actual: Kt43517Kt.compareEnums(e1: Kt43517Kt.produceEnum(), e2: Kt43517Kt.produceEnum()),
expected: true
)
try assertEquals(
actual: Kt43517Kt.getFirstField(s: Kt43517Kt.getGlobalS()),
expected: 3
)
}
class Kt43517Tests : TestProvider {
var tests: [TestCase] = []
init() {
providers.append(self)
tests = [
TestCase(name: "Kt43517", method: withAutorelease(testKt43517)),
]
}
}
@@ -0,0 +1,4 @@
enum class SimpleEnum {
ONE,
TWO
}
@@ -0,0 +1,49 @@
import Kt56233
func threadRoutine(pointer: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer? {
autoreleasepool {
let f = pointer.bindMemory(to: (() -> ()).self, capacity: 1).pointee
f()
}
return nil
}
func launchThreads(
_ f: @convention(c) () -> (),
threadCount: Int = 4
) throws {
var threads: [pthread_t] = []
for _ in 0..<threadCount {
let fPtr = UnsafeMutablePointer<() -> ()>.allocate(capacity: 1)
fPtr.initialize(to: f)
var thread: pthread_t? = nil
let result = pthread_create(&thread, nil, threadRoutine, fPtr)
try assertEquals(actual: result, expected: 0)
threads.append(thread!)
}
for thread in threads {
pthread_join(thread, nil)
}
}
func kt56233() {
#if AGGRESSIVE_GC
let count = 50_000
#else
let count = 50_000_000
#endif
// Stress testing for race conditions.
for _ in 0..<count {
_ = Kt56233.SimpleEnum.two.ordinal
}
}
// -------- Execution of the test --------
class Kt56233Tests : SimpleTestProvider {
override init() {
super.init()
test("Kt56233", { try launchThreads(kt56233) })
}
}
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2023 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.
*/
interface Foo {
fun bar(): String?
}
internal class FooImplUnused : Foo {
override fun bar(): String? = null
}
fun foobar(foo: Foo): Boolean {
val s = foo.bar()
if (s == null)
return false
return s == "zzz"
}
@@ -0,0 +1,21 @@
import Foundation
import Kt57791
class FooImpl : Foo {
func bar() -> String? { "zzz" }
}
func testKt57791() throws {
try assertTrue(Kt57791Kt.foobar(foo: FooImpl()))
}
class Kt57791Tests : TestProvider {
var tests: [TestCase] = []
init() {
providers.append(self)
tests = [
TestCase(name: "Kt57791", method: withAutorelease(testKt57791)),
]
}
}
+247
View File
@@ -0,0 +1,247 @@
/*
* Copyright 2010-2018 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Foundation
enum TestError : Error {
case assertFailed(String)
case failure
case testsFailed([String])
}
// ---------------- Assertions ----------------
private func throwAssertFailed(message: String, file: String, line: Int) throws -> Never {
throw TestError.assertFailed("\(file):\(line): \(message)")
}
func assertEquals<T: Equatable>(actual: T, expected: T,
_ message: String = "Assertion failed:",
file: String = #file, line: Int = #line) throws {
if (actual != expected) {
try throwAssertFailed(message: message + " Expected value: \(expected), but got: \(actual)",
file: file, line: line)
}
}
func assertSame(actual: AnyObject?, expected: AnyObject?,
_ message: String = "Assertion failed:",
file: String = #file, line: Int = #line) throws {
if (actual !== expected) {
try throwAssertFailed(message: message + " Expected value: \(expected), but got: \(actual)",
file: file, line: line)
}
}
func assertEquals<T: Equatable>(actual: [T], expected: [T],
_ message: String = "Assertion failed: arrays not equal",
file: String = #file, line: Int = #line) throws {
try assertEquals(actual: actual.count, expected: expected.count, "Size differs", file: file, line: line)
try assertTrue(actual.elementsEqual(expected), "Arrays elements are not equal", file: file, line: line)
}
func assertTrue(_ value: Bool,
_ message: String = "Assertion failed:",
file: String = #file, line: Int = #line) throws {
if (value != true) {
try throwAssertFailed(message: message + " Expected value to be TRUE, but got: \(value)",
file: file, line: line)
}
}
func assertFalse(_ value: Bool,
_ message: String = "Assertion failed:",
file: String = #file, line: Int = #line) throws {
if (value != false) {
try throwAssertFailed(message: message + " Expected value to be FALSE, but got: \(value)",
file: file, line: line)
}
}
func assertNil(_ value: Any?,
_ message: String = "Assertion failed:",
file: String = #file, line: Int = #line) throws {
if (value != nil) {
try throwAssertFailed(message: message + " Expected value to be nil, but got: \(value!)",
file: file, line: line)
}
}
func fail(_ message: String = "Should not reach here", file: String = #file, line: Int = #line) throws -> Never {
try throwAssertFailed(message: message, file: file, line: line)
}
func assertFailsWith<T : Error>(_ errorType: T.Type,
_ message: String = "Assertion failed:",
file: String = #file, line: Int = #line,
block: () throws -> Void) throws {
do {
try block()
} catch let error {
if error is T { return }
try throwAssertFailed(message: message + " Expected error \(errorType), got \(error)",
file: file, line: line)
}
try throwAssertFailed(message: message + " Expected error \(errorType), but finished successfully",
file: file, line: line)
}
func assertFailsWithKotlin<T>(_ exceptionType: T.Type,
_ message: String = "Assertion failed:",
file: String = #file, line: Int = #line,
block: () throws -> Void) throws {
do {
try block()
} catch let error {
let kotlinException = error.kotlinException
if kotlinException is T { return }
let got = kotlinException ?? error
try throwAssertFailed(message: message + " Expected Kotlin exception \(exceptionType), got \(got)",
file: file, line: line)
}
try throwAssertFailed(message: message + " Expected Kotlin exception \(exceptionType), but finished successfully",
file: file, line: line)
}
// ---------------- Utils --------------------
func withAutorelease( _ method: @escaping () throws -> Void) -> () throws -> Void {
return { () throws -> Void in
try autoreleasepool { try method() }
}
}
extension Error {
var kotlinException: Any? {
get {
return (self as NSError).userInfo["KotlinException"]
}
}
}
// ---------------- Execution ----------------
private final class Statistics : CustomStringConvertible {
var passed: [String] = []
var failed: [String] = []
var description: String {
return """
---- RESULTS:
PASSED: \(passed.count)
FAILED: \(failed.count)
"""
}
static let instance = Statistics()
static func getInstance() -> Statistics {
return instance
}
func start(_ name: String) {
print("---- Starting test: \(name)")
}
func passed(_ name: String) {
print("---- PASSED test: \(name)")
passed.append(name)
}
func failed(_ name: String, error: Error) {
print("---- FAILED test: \(name) with error: \(error)")
failed.append(name)
}
}
/**
* TestCase represents a single test
*/
struct TestCase {
let name: String
let method: () throws -> Void
init(name: String, method: @escaping () throws -> Void) {
self.name = name
self.method = method
}
func run() {
let stats = Statistics.getInstance()
stats.start(name)
do {
try method()
stats.passed(name)
} catch {
stats.failed(name, error: error)
}
}
}
protocol TestProvider {
var tests: [TestCase] { get }
}
class SimpleTestProvider : TestProvider {
var tests: [TestCase] = []
init() {
providers.append(self)
}
func test(_ name: String, _ method: @escaping () throws -> Void) {
tests.append(TestCase(name: name, method: withAutorelease(method)))
}
}
var providers: [TestProvider] = []
private func execute(tests: [TestCase]) {
for test in tests {
test.run()
}
}
/**
* Entry point of the test
*/
private func main() {
// Generated method that instantiates test providers.
registerProviders()
let stats = Statistics.getInstance()
for pr in providers {
let name = String(describing: type(of: pr))
print("-- \(name) started")
execute(tests: pr.tests)
print("-- \(name) finished")
}
print(stats)
let failed = stats.failed
if !failed.isEmpty {
print()
print("Tests failed:")
for testName in failed {
print(":: \(testName)")
}
abort()
}
}
main()
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
@file:Suppress("UNUSED")
package multiple
interface I1 {
fun getFortyTwo(): Int
}
class I1Impl : I1 {
override fun getFortyTwo(): Int = 42
}
fun getI1() = object : I1 {
override fun getFortyTwo(): Int = 42
}
class C
fun getUnit(): Unit? = Unit
/*
// Disabled for now to avoid depending on platform libs.
fun getAnonymousObject() = object : platform.darwin.NSObject() {}
class NamedObject : platform.darwin.NSObject()
fun getNamedObject() = NamedObject()
*/
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
@file:Suppress("UNUSED")
package multiple
val name = "first"
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
@file:Suppress("UNUSED")
package multiple
interface I2 {
fun getFortyTwo(): Int
}
fun getFortyTwoFrom(i2: I2): Int = i2.getFortyTwo()
fun getI2() = object : I2 {
override fun getFortyTwo(): Int = 42
}
class C
fun isUnit(obj: Any?): Boolean = (obj === Unit)
/*
// Disabled for now to avoid depending on platform libs.
fun getAnonymousObject() = object : platform.darwin.NSObject() {}
class NamedObject : platform.darwin.NSObject()
fun getNamedObject() = NamedObject()
*/
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
@file:Suppress("UNUSED")
package multiple
val name = "second"
@@ -0,0 +1,86 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import First
import Second
func testClashingNames() throws {
try assertEquals(actual: "first", expected: First.TestKt.name)
try assertEquals(actual: "second", expected: Second.TestKt.name)
let c1 = First.C()
let c2 = Second.C()
try assertTrue(type(of: c1) == First.C.self)
try assertTrue(type(of: c2) == Second.C.self)
try assertTrue(First.C.self != Second.C.self)
try assertTrue(objc_getClass(class_getName(First.C.self)) as AnyObject === First.C.self)
try assertTrue(objc_getClass(class_getName(Second.C.self)) as AnyObject === Second.C.self)
}
extension I1Impl : I2 {}
func testInteraction() throws {
try assertEquals(actual: SecondKt.getFortyTwoFrom(i2: I1Impl()), expected: 42)
}
func testIsolation1() throws {
try assertFalse(SecondKt.isUnit(obj: FirstKt.getUnit()))
// Ensure frameworks don't share the same runtime (state):
try assertFalse(First.RuntimeState().consumeChange())
try assertFalse(Second.RuntimeState().consumeChange())
Second.RuntimeState().produceChange()
try assertFalse(First.RuntimeState().consumeChange())
try assertTrue(Second.RuntimeState().consumeChange())
}
func testIsolation2() throws {
try assertEquals(actual: FirstKt.getI1().getFortyTwo(), expected: 42)
try assertEquals(actual: SecondKt.getI2().getFortyTwo(), expected: 42)
}
func testIsolation3() throws {
#if false // Disabled for now to avoid depending on platform libs.
FirstKt.getAnonymousObject()
SecondKt.getAnonymousObject()
FirstKt.getNamedObject()
SecondKt.getNamedObject()
#endif
}
// https://youtrack.jetbrains.com/issue/KT-34261
// When First and Second are static frameworks with caches, this test fails due to bad cache isolation:
// Caches included into both frameworks have 'ktypew' globals (with same name, hidden visibility and common linkage)
// for writable part of this "unexposed stdlib class" TypeInfo.
// ld ignores hidden visibility and merges common globals, so two independent frameworks happen to share
// the same global instead of two different globals. Things go wrong at runtime then: this writable TypeInfo part
// is used to store Obj-C class for this Kotlin class. So after the first object is obtained in Swift, both TypeInfos
// have its class, and the second object is wrong then.
func testIsolation4() throws {
let obj1: Any = First.SharedKt.getUnexposedStdlibClassInstance()
try assertTrue(obj1 is First.KotlinBase)
try assertFalse(obj1 is Second.KotlinBase)
let obj2: Any = Second.SharedKt.getUnexposedStdlibClassInstance()
try assertFalse(obj2 is First.KotlinBase)
try assertTrue(obj2 is Second.KotlinBase)
}
class MultipleTests : TestProvider {
var tests: [TestCase] = []
init() {
tests = [
TestCase(name: "TestClashingNames", method: withAutorelease(testClashingNames)),
TestCase(name: "TestInteraction", method: withAutorelease(testInteraction)),
TestCase(name: "TestIsolation1", method: withAutorelease(testIsolation1)),
TestCase(name: "TestIsolation2", method: withAutorelease(testIsolation2)),
TestCase(name: "TestIsolation3", method: withAutorelease(testIsolation3)),
TestCase(name: "TestIsolation4", method: withAutorelease(testIsolation4)),
]
providers.append(self)
}
}
@@ -0,0 +1,15 @@
@file:OptIn(ObsoleteWorkersApi::class)
import kotlin.native.concurrent.*
object RuntimeState {
fun produceChange() {
Worker.current.executeAfter {}
}
fun consumeChange(): Boolean {
return Worker.current.processQueue()
}
}
// Note: this assumes that IntRange class is not exposed by the enclosing framework.
fun getUnexposedStdlibClassInstance(): Any = 0..2
@@ -0,0 +1,248 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
@file:OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
package coroutines
import kotlin.coroutines.*
import kotlin.coroutines.cancellation.CancellationException
import kotlin.coroutines.intrinsics.*
import kotlin.native.concurrent.isFrozen
import kotlin.native.internal.ObjCErrorException
import kotlin.test.*
import kotlin.reflect.*
class CoroutineException : Throwable()
suspend fun suspendFun() = 42
suspend fun unitSuspendFun() = Unit
@Throws(CoroutineException::class, CancellationException::class)
suspend fun suspendFun(result: Any?, doSuspend: Boolean, doThrow: Boolean): Any? {
if (doSuspend) {
suspendCoroutineUninterceptedOrReturn<Unit> {
it.resume(Unit)
COROUTINE_SUSPENDED
}
}
if (doThrow) throw CoroutineException()
return result
}
@Throws(CoroutineException::class, CancellationException::class)
suspend fun unitSuspendFun(doSuspend: Boolean, doThrow: Boolean) {
if (doSuspend) {
suspendCoroutineUninterceptedOrReturn<Unit> {
it.resume(Unit)
COROUTINE_SUSPENDED
}
}
if (doThrow) throw CoroutineException()
}
class ContinuationHolder<T> {
internal var continuation: Continuation<T>? = null
fun resume(value: T) {
continuation!!.resume(value)
continuation = null
}
fun resumeWithException(exception: Throwable) {
continuation!!.resumeWithException(exception)
continuation = null
}
}
@Throws(CoroutineException::class, CancellationException::class)
suspend fun suspendFunAsync(result: Any?, continuationHolder: ContinuationHolder<Any?>): Any? =
suspendCoroutineUninterceptedOrReturn<Any?> {
continuationHolder.continuation = it
COROUTINE_SUSPENDED
} ?: result
@Throws(CoroutineException::class, CancellationException::class)
suspend fun unitSuspendFunAsync(continuationHolder: ContinuationHolder<Unit>): Unit =
suspendCoroutineUninterceptedOrReturn<Unit> {
continuationHolder.continuation = it
COROUTINE_SUSPENDED
}
@Throws(CoroutineException::class, CancellationException::class)
fun throwException(exception: Throwable) {
throw exception
}
interface SuspendFun {
@Throws(CoroutineException::class, CancellationException::class)
suspend fun suspendFun(doYield: Boolean, doThrow: Boolean): Int
}
class ResultHolder<T> {
var completed: Int = 0
var result: T? = null
var exception: Throwable? = null
internal fun complete(result: Result<T>) {
this.result = result.getOrNull()
this.exception = result.exceptionOrNull()
this.completed += 1
}
}
private class ResultHolderCompletion<T>(val resultHolder: ResultHolder<T>) : Continuation<T> {
override val context: CoroutineContext
get() = EmptyCoroutineContext
override fun resumeWith(result: Result<T>) {
resultHolder.complete(result)
}
}
fun callSuspendFun(suspendFun: SuspendFun, doYield: Boolean, doThrow: Boolean, resultHolder: ResultHolder<Int>) {
suspend { suspendFun.suspendFun(doYield = doYield, doThrow = doThrow) }
.startCoroutine(ResultHolderCompletion(resultHolder))
}
@Throws(CoroutineException::class, CancellationException::class)
suspend fun callSuspendFun2(suspendFun: SuspendFun, doYield: Boolean, doThrow: Boolean): Int {
return suspendFun.suspendFun(doYield = doYield, doThrow = doThrow)
}
interface SuspendBridge<T> {
suspend fun int(value: T): Int
suspend fun intAsAny(value: T): Any?
suspend fun unit(value: T): Unit
suspend fun unitAsAny(value: T): Any?
suspend fun nullableUnit(value: T): Unit?
@Throws(Throwable::class) suspend fun nothing(value: T): Nothing
@Throws(Throwable::class) suspend fun nothingAsInt(value: T): Int
@Throws(Throwable::class) suspend fun nothingAsAny(value: T): Any?
@Throws(Throwable::class) suspend fun nothingAsUnit(value: T): Unit
}
abstract class AbstractSuspendBridge : SuspendBridge<Int> {
override suspend fun intAsAny(value: Int): Int = TODO()
override suspend fun unit(value: Int): Unit = TODO()
override suspend fun unitAsAny(value: Int): Unit = TODO()
override suspend fun nullableUnit(value: Int): Unit? = TODO()
override suspend fun nothingAsInt(value: Int): Nothing = TODO()
override suspend fun nothingAsAny(value: Int): Nothing = TODO()
override suspend fun nothingAsUnit(value: Int): Nothing = TODO()
}
private suspend fun callSuspendBridgeImpl(bridge: SuspendBridge<Int>) {
assertEquals(1, bridge.intAsAny(1))
assertSame(Unit, bridge.unit(2))
assertSame(Unit, bridge.unitAsAny(3))
assertSame(Unit, bridge.nullableUnit(4))
assertFailsWith<ObjCErrorException> { bridge.nothingAsInt(5) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsAny(6) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsUnit(7) }
}
private suspend fun callAbstractSuspendBridgeImpl(bridge: AbstractSuspendBridge) {
assertEquals(8, bridge.intAsAny(8))
assertSame(Unit, bridge.unit(9))
assertSame(Unit, bridge.unitAsAny(10))
assertSame(Unit, bridge.nullableUnit(11))
assertFailsWith<ObjCErrorException> { bridge.nothingAsInt(12) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsAny(13) }
assertFailsWith<ObjCErrorException> { bridge.nothingAsUnit(14) }
}
@Throws(Throwable::class)
fun callSuspendBridge(bridge: AbstractSuspendBridge, resultHolder: ResultHolder<Unit>) {
suspend {
callSuspendBridgeImpl(bridge)
callAbstractSuspendBridgeImpl(bridge)
}.startCoroutine(ResultHolderCompletion(resultHolder))
}
suspend fun throwCancellationException(): Unit {
val exception = CancellationException("coroutine is cancelled")
// Note: frontend checker hardcodes fq names of CancellationException super classes (see NativeThrowsChecker).
// This is our best effort to keep that list in sync with actual stdlib code:
assertTrue(exception is kotlin.Throwable)
assertTrue(exception is kotlin.Exception)
assertTrue(exception is kotlin.RuntimeException)
assertTrue(exception is kotlin.IllegalStateException)
assertTrue(exception is kotlin.coroutines.cancellation.CancellationException)
throw exception
}
abstract class ThrowCancellationException {
internal abstract suspend fun throwCancellationException()
}
class ThrowCancellationExceptionImpl : ThrowCancellationException() {
public override suspend fun throwCancellationException() {
throw CancellationException()
}
}
class suspendFunctionChild0: suspend () -> String {
override suspend fun invoke(): String = "child 0"
}
class suspendFunctionChild1: suspend (String) -> String {
override suspend fun invoke(s: String): String = "$s 1"
}
fun getSuspendLambda0(): suspend () -> String = { "lambda 0" }
private suspend fun suspendCallableReference0Target(): String = "callable reference 0"
fun getSuspendCallableReference0(): suspend () -> String = ::suspendCallableReference0Target
fun getSuspendChild0() = suspendFunctionChild0()
fun getSuspendLambda1(): suspend (String) -> String = { "$it 1" }
private suspend fun suspendCallableReference1Target(str: String): String = "$str 1"
fun getSuspendCallableReference1(): suspend (String) -> String = ::suspendCallableReference1Target
fun getSuspendChild1() = suspendFunctionChild1()
suspend fun invoke1(block: suspend (Any?) -> Any?, argument: Any?): Any? = block(argument)
fun getKSuspendCallableReference0(): KSuspendFunction0<String> = ::suspendCallableReference0Target
fun getKSuspendCallableReference1(): KSuspendFunction1<String, String> = ::suspendCallableReference1Target
@Throws(Throwable::class)
fun startCoroutineUninterceptedOrReturn(fn: suspend () -> Any?, resultHolder: ResultHolder<Any?>) =
fn.startCoroutineUninterceptedOrReturn(ResultHolderCompletion(resultHolder))
@Throws(Throwable::class)
fun startCoroutineUninterceptedOrReturn(fn: suspend Any?.() -> Any?, receiver: Any?, resultHolder: ResultHolder<Any?>) =
fn.startCoroutineUninterceptedOrReturn(receiver, ResultHolderCompletion(resultHolder))
@Throws(Throwable::class)
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
fun startCoroutineUninterceptedOrReturn(fn: suspend Any?.(Any?) -> Any?, receiver: Any?, param: Any?, resultHolder: ResultHolder<Any?>) =
fn.startCoroutineUninterceptedOrReturn(receiver, param, ResultHolderCompletion(resultHolder))
@Throws(Throwable::class)
fun createCoroutineUninterceptedAndResume(fn: suspend () -> Any?, resultHolder: ResultHolder<Any?>) =
fn.createCoroutine(ResultHolderCompletion(resultHolder)).resume(Unit)
@Throws(Throwable::class)
fun createCoroutineUninterceptedAndResume(fn: suspend Any?.() -> Any?, receiver: Any?, resultHolder: ResultHolder<Any?>) =
fn.createCoroutine(receiver, ResultHolderCompletion(resultHolder)).resume(Unit)
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
fun gc() = kotlin.native.runtime.GC.collect()
@@ -0,0 +1,741 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
private func testCallSimple() throws {
var result: KotlinInt? = nil
var error: Error? = nil
var completionCalled = 0
CoroutinesKt.suspendFun { _result, _error in
completionCalled += 1
result = _result
error = _error
}
try assertEquals(actual: completionCalled, expected: 1)
try assertEquals(actual: result, expected: 42)
try assertNil(error)
}
private func testUnitCallSimple() throws {
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
var result: KotlinUnit? = nil
#endif
var error: Error? = nil
var completionCalled = 0
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
CoroutinesKt.unitSuspendFun { _result, _error in
completionCalled += 1
result = _result
error = _error
}
#else
CoroutinesKt.unitSuspendFun { _error in
completionCalled += 1
error = _error
}
#endif
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
try assertSame(actual: result, expected: KotlinUnit.shared)
#endif
try assertEquals(actual: completionCalled, expected: 1)
try assertNil(error)
}
private func testUnitCallNonMainDispatcher() throws {
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
var result: KotlinUnit? = nil
#endif
var error: Error? = nil
var completionCalled = 0
let group = DispatchGroup()
#if ALLOW_SUSPEND_ANY_THREAD
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
DispatchQueue.global().async(group: group) {
CoroutinesKt.unitSuspendFun { _result, _error in
completionCalled += 1
result = _result
error = _error
}
}
#else
DispatchQueue.global().async(group: group) {
CoroutinesKt.unitSuspendFun { _error in
completionCalled += 1
error = _error
}
}
#endif
#endif
#if ALLOW_SUSPEND_ANY_THREAD
group.wait()
try assertEquals(actual: completionCalled, expected: 1)
#endif
}
private func testCallSuspendFun(doSuspend: Bool, doThrow: Bool) throws {
class C {}
let expectedResult = C()
var completionCalled = 0
var result: AnyObject? = nil
var error: Error? = nil
CoroutinesKt.suspendFun(result: expectedResult, doSuspend: doSuspend, doThrow: doThrow) { _result, _error in
completionCalled += 1
result = _result as AnyObject?
error = _error
}
try assertEquals(actual: completionCalled, expected: 1)
if doThrow {
try assertNil(result)
try assertTrue(error?.kotlinException is CoroutineException)
} else {
try assertSame(actual: result, expected: expectedResult)
try assertNil(error)
}
}
private func testCallUnitSuspendFun(doSuspend: Bool, doThrow: Bool) throws {
var completionCalled = 0
var result: AnyObject? = nil
var error: Error? = nil
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
CoroutinesKt.unitSuspendFun(doSuspend: doSuspend, doThrow: doThrow) { _result, _error in
completionCalled += 1
result = _result as AnyObject?
error = _error
}
#else
CoroutinesKt.unitSuspendFun(doSuspend: doSuspend, doThrow: doThrow) { _error in
completionCalled += 1
error = _error
}
#endif
try assertEquals(actual: completionCalled, expected: 1)
if doThrow {
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
try assertNil(result)
#endif
try assertTrue(error?.kotlinException is CoroutineException)
} else {
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
try assertSame(actual: result, expected: KotlinUnit.shared)
#endif
try assertNil(error)
}
}
private class WeakRefHolder {
weak var value: AnyObject? = nil
}
#if NO_GENERICS
typealias AnyContinuationHolder = ContinuationHolder
#else
typealias AnyContinuationHolder = ContinuationHolder<AnyObject>
#endif
// This code is extracted to a function just to ensure that all local variables get released at the end.
private func callSuspendFunAsync(
weakRefToObjectCapturedByCompletion: WeakRefHolder,
continuationHolder: AnyContinuationHolder,
completionHandler: @escaping (Any?, Error?) -> Void
) throws {
class C {}
let capturedByCompletion = C()
weakRefToObjectCapturedByCompletion.value = capturedByCompletion
CoroutinesKt.suspendFunAsync(result: nil, continuationHolder: continuationHolder) { _result, _error in
try! assertSame(actual: capturedByCompletion, expected: weakRefToObjectCapturedByCompletion.value)
completionHandler(_result, _error)
}
}
private func testSuspendFuncAsync(doThrow: Bool) throws {
var completionCalled = 0
var result: AnyObject? = nil
var error: Error? = nil
let continuationHolder = AnyContinuationHolder()
let weakRefToObjectCapturedByCompletion = WeakRefHolder()
try assertTrue(weakRefToObjectCapturedByCompletion.value === nil)
try autoreleasepool {
try callSuspendFunAsync(
weakRefToObjectCapturedByCompletion: weakRefToObjectCapturedByCompletion,
continuationHolder: continuationHolder
) { _result, _error in
completionCalled += 1
result = _result as AnyObject?
error = _error
}
}
CoroutinesKt.gc()
// This assert checks that suspendFunAsync retains the completion handler:
try assertFalse(weakRefToObjectCapturedByCompletion.value === nil)
try assertEquals(actual: completionCalled, expected: 0)
if doThrow {
let exception = CoroutineException()
continuationHolder.resumeWithException(exception: exception)
try assertEquals(actual: completionCalled, expected: 1)
try assertNil(result)
try assertSame(actual: error?.kotlinException as AnyObject?, expected: exception)
} else {
class C {}
let expectedResult = C()
continuationHolder.resume(value: expectedResult)
try assertEquals(actual: completionCalled, expected: 1)
try assertSame(actual: result, expected: expectedResult)
try assertNil(error)
}
#if !NOOP_GC
CoroutinesKt.gc()
// This assert checks that the completion handler gets properly released after all:
try assertTrue(weakRefToObjectCapturedByCompletion.value === nil)
#endif
}
#if NO_GENERICS
typealias UnitContinuationHolder = ContinuationHolder
#else
typealias UnitContinuationHolder = ContinuationHolder<KotlinUnit>
#endif
// This code is extracted to a function just to ensure that all local variables get released at the end.
private func callUnitSuspendFunAsync(
weakRefToObjectCapturedByCompletion: WeakRefHolder,
continuationHolder: UnitContinuationHolder,
completionHandler: @escaping (Error?) -> Void
) throws {
class C {}
let capturedByCompletion = C()
weakRefToObjectCapturedByCompletion.value = capturedByCompletion
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
CoroutinesKt.unitSuspendFunAsync(continuationHolder: continuationHolder) { _result, _error in
try! assertSame(actual: capturedByCompletion, expected: weakRefToObjectCapturedByCompletion.value)
completionHandler(_error)
}
#else
CoroutinesKt.unitSuspendFunAsync(continuationHolder: continuationHolder) { _error in
try! assertSame(actual: capturedByCompletion, expected: weakRefToObjectCapturedByCompletion.value)
completionHandler(_error)
}
#endif
}
private func testUnitSuspendFuncAsync(doThrow: Bool) throws {
var completionCalled = 0
var error: Error? = nil
let continuationHolder = UnitContinuationHolder()
let weakRefToObjectCapturedByCompletion = WeakRefHolder()
try assertTrue(weakRefToObjectCapturedByCompletion.value === nil)
try autoreleasepool {
try callUnitSuspendFunAsync(
weakRefToObjectCapturedByCompletion: weakRefToObjectCapturedByCompletion,
continuationHolder: continuationHolder
) { _error in
completionCalled += 1
error = _error
}
}
CoroutinesKt.gc()
// This assert checks that unitSuspendFunAsync retains the completion handler:
try assertFalse(weakRefToObjectCapturedByCompletion.value === nil)
try assertEquals(actual: completionCalled, expected: 0)
if doThrow {
let exception = CoroutineException()
continuationHolder.resumeWithException(exception: exception)
try assertEquals(actual: completionCalled, expected: 1)
try assertSame(actual: error?.kotlinException as AnyObject?, expected: exception)
} else {
continuationHolder.resume(value: KotlinUnit.shared)
try assertEquals(actual: completionCalled, expected: 1)
try assertNil(error)
}
#if !NOOP_GC
CoroutinesKt.gc()
// This assert checks that the completion handler gets properly released after all:
try assertTrue(weakRefToObjectCapturedByCompletion.value === nil)
#endif
}
private func testCall() throws {
try testCallSuspendFun(doSuspend: true, doThrow: false)
try testCallSuspendFun(doSuspend: false, doThrow: false)
try testCallSuspendFun(doSuspend: true, doThrow: true)
try testCallSuspendFun(doSuspend: false, doThrow: true)
try testCallUnitSuspendFun(doSuspend: true, doThrow: false)
try testCallUnitSuspendFun(doSuspend: false, doThrow: false)
try testCallUnitSuspendFun(doSuspend: true, doThrow: true)
try testCallUnitSuspendFun(doSuspend: false, doThrow: true)
try testSuspendFuncAsync(doThrow: false)
try testSuspendFuncAsync(doThrow: true)
try testUnitSuspendFuncAsync(doThrow: false)
try testUnitSuspendFuncAsync(doThrow: true)
}
private func testCallSuspendFunChain(doSuspend: Bool, doThrow: Bool) throws {
class C {}
let expectedResult = C()
var completionCalled = 0
var result: AnyObject? = nil
var error: Error? = nil
CoroutinesKt.suspendFun(result: expectedResult, doSuspend: doSuspend, doThrow: doThrow) { _resultOuter, _errorOuter in
CoroutinesKt.suspendFun(result: expectedResult, doSuspend: doSuspend, doThrow: doThrow) { _result, _error in
completionCalled += 1
result = _result as AnyObject?
error = _error
}
}
try assertEquals(actual: completionCalled, expected: 1)
if doThrow {
try assertNil(result)
try assertTrue(error?.kotlinException is CoroutineException)
} else {
try assertSame(actual: result, expected: expectedResult)
try assertNil(error)
}
}
private func testCallChain() throws {
try testCallSuspendFunChain(doSuspend: true, doThrow: false)
try testCallSuspendFunChain(doSuspend: false, doThrow: false)
try testCallSuspendFunChain(doSuspend: true, doThrow: true)
try testCallSuspendFunChain(doSuspend: false, doThrow: true)
}
private class SuspendFunImpl : SuspendFun {
class E : Error {}
var completion: (() -> Void)? = nil
func suspendFun(doYield: Bool, doThrow: Bool, completionHandler: @escaping (KotlinInt?, Error?) -> Void) {
func callCompletion() {
if doThrow {
completionHandler(nil, E())
} else {
completionHandler(17, nil)
}
}
if doYield {
self.completion = callCompletion
} else {
callCompletion()
}
}
}
private func testSuspendFunImpl(doYield: Bool, doThrow: Bool) throws {
#if NO_GENERICS
let resultHolder = ResultHolder()
#else
let resultHolder = ResultHolder<KotlinInt>()
#endif
let impl = SuspendFunImpl()
CoroutinesKt.callSuspendFun(
suspendFun: impl,
doYield: doYield,
doThrow: doThrow,
resultHolder: resultHolder
)
if doYield {
try assertEquals(actual: resultHolder.completed, expected: 0)
guard let completion = impl.completion else { try fail() }
completion()
}
try assertEquals(actual: resultHolder.completed, expected: 1)
if doThrow {
try assertNil(resultHolder.result)
if let e = resultHolder.exception {
try assertFailsWith(SuspendFunImpl.E.self) { try CoroutinesKt.throwException(exception: e) }
} else {
try fail()
}
} else {
try assertEquals(actual: resultHolder.result as! Int, expected: 17)
try assertNil(resultHolder.exception)
}
}
private func testSuspendFunImpl2(doYield: Bool, doThrow: Bool) throws {
let impl = SuspendFunImpl()
var completionCalled = 0
var result: KotlinInt? = nil
var error: Error? = nil
CoroutinesKt.callSuspendFun2(suspendFun: impl, doYield: doYield, doThrow: doThrow) { _result, _error in
completionCalled += 1
result = _result
error = _error
}
if doYield {
try assertEquals(actual: completionCalled, expected: 0)
guard let completion = impl.completion else { try fail() }
completion()
}
try assertEquals(actual: completionCalled, expected: 1)
if doThrow {
try assertNil(result)
try assertTrue(error is SuspendFunImpl.E)
} else {
try assertEquals(actual: result, expected: 17)
try assertNil(error)
}
}
private func testOverride() throws {
try testSuspendFunImpl(doYield: false, doThrow: false)
try testSuspendFunImpl(doYield: false, doThrow: true)
try testSuspendFunImpl(doYield: true, doThrow: false)
try testSuspendFunImpl(doYield: true, doThrow: true)
try testSuspendFunImpl2(doYield: false, doThrow: false)
try testSuspendFunImpl2(doYield: false, doThrow: true)
try testSuspendFunImpl2(doYield: true, doThrow: false)
try testSuspendFunImpl2(doYield: true, doThrow: true)
}
private class SwiftSuspendBridge : AbstractSuspendBridge {
class E : Error {}
override func intAsAny(value: KotlinInt, completionHandler: @escaping (KotlinInt?, Error?) -> Void) {
completionHandler(value, nil)
}
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
override func unit(value: KotlinInt, completionHandler: @escaping (KotlinUnit?, Error?) -> Void) {
completionHandler(KotlinUnit(), nil)
}
#else
override func unit(value: KotlinInt, completionHandler: @escaping (Error?) -> Void) {
completionHandler(nil)
}
#endif
override func unitAsAny(value: KotlinInt, completionHandler: @escaping (KotlinUnit?, Error?) -> Void) {
completionHandler(KotlinUnit(), nil)
}
override func nullableUnit(value: KotlinInt, completionHandler: @escaping (KotlinUnit?, Error?) -> Void) {
completionHandler(KotlinUnit(), nil)
}
override func nothingAsInt(value: KotlinInt, completionHandler: @escaping (KotlinNothing?, Error?) -> Void) {
completionHandler(nil, E())
}
override func nothingAsAny(value: KotlinInt, completionHandler: @escaping (KotlinNothing?, Error?) -> Void) {
completionHandler(nil, E())
}
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
override func nothingAsUnit(value: KotlinInt, completionHandler: @escaping (KotlinNothing?, Error?) -> Void) {
completionHandler(nil, E())
}
#else
override func nothingAsUnit(value: KotlinInt, completionHandler: @escaping (Error?) -> Void) {
completionHandler(E())
}
#endif
}
private func testBridges() throws {
#if NO_GENERICS
let resultHolder = ResultHolder()
#else
let resultHolder = ResultHolder<KotlinUnit>()
#endif
try CoroutinesKt.callSuspendBridge(bridge: SwiftSuspendBridge(), resultHolder: resultHolder)
try assertEquals(actual: resultHolder.completed, expected: 1)
try assertNil(resultHolder.exception)
try assertSame(actual: resultHolder.result as AnyObject, expected: KotlinUnit())
}
private func testImplicitThrows1() throws {
var error: Error? = nil
var completionCalled = 0
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
var result: KotlinUnit? = nil
CoroutinesKt.throwCancellationException { _result, _error in
completionCalled += 1
result = _result
error = _error
}
try assertNil(result)
#else
CoroutinesKt.throwCancellationException { _error in
completionCalled += 1
error = _error
}
#endif
try assertEquals(actual: completionCalled, expected: 1)
try assertTrue(error?.kotlinException is KotlinCancellationException)
}
private func testImplicitThrows2() throws {
var error: Error? = nil
var completionCalled = 0
#if LEGACY_SUSPEND_UNIT_FUNCTION_EXPORT
var result: KotlinUnit? = nil
ThrowCancellationExceptionImpl().throwCancellationException { _result, _error in
completionCalled += 1
result = _result
error = _error
}
try assertNil(result)
#else
ThrowCancellationExceptionImpl().throwCancellationException { _error in
completionCalled += 1
error = _error
}
#endif
try assertEquals(actual: completionCalled, expected: 1)
try assertTrue(error?.kotlinException is KotlinCancellationException)
}
private func testSuspendFunctionType0(f: KotlinSuspendFunction0, expectedResult: String) throws {
try assertTrue((f as AnyObject) is KotlinSuspendFunction0)
var result: String? = nil
var error: Error? = nil
var completionCalled = 0
f.invoke { _result, _error in
completionCalled += 1
result = _result as? String
error = _error
}
try assertEquals(actual: completionCalled, expected: 1)
try assertEquals(actual: result, expected: expectedResult)
try assertNil(error)
}
private func testSuspendFunctionType1(f: KotlinSuspendFunction1) throws {
try assertTrue((f as AnyObject) is KotlinSuspendFunction1)
var result: String? = nil
var error: Error? = nil
var completionCalled = 0
f.invoke(p1: "suspend function type") { _result, _error in
completionCalled += 1
result = _result as? String
error = _error
}
try assertEquals(actual: completionCalled, expected: 1)
try assertEquals(actual: result, expected: "suspend function type 1")
try assertNil(error)
}
private func testSuspendFunctionType() throws {
try testSuspendFunctionType0(f: CoroutinesKt.getSuspendLambda0(), expectedResult: "lambda 0")
try testSuspendFunctionType0(f: CoroutinesKt.getSuspendCallableReference0(), expectedResult: "callable reference 0")
try testSuspendFunctionType0(f: CoroutinesKt.getSuspendChild0(), expectedResult: "child 0")
try testSuspendFunctionType1(f: CoroutinesKt.getSuspendLambda1())
try testSuspendFunctionType1(f: CoroutinesKt.getSuspendCallableReference1())
try testSuspendFunctionType1(f: CoroutinesKt.getSuspendChild1())
}
private func testKSuspendFunctionType0(f: KotlinKSuspendFunction0, expectedResult: String) throws {
try assertTrue((f as AnyObject) is KotlinKSuspendFunction0)
var result: String? = nil
var error: Error? = nil
var completionCalled = 0
f.invoke { _result, _error in
completionCalled += 1
result = _result as? String
error = _error
}
try assertEquals(actual: completionCalled, expected: 1)
try assertEquals(actual: result, expected: expectedResult)
try assertNil(error)
}
private func testKSuspendFunctionType1(f: KotlinKSuspendFunction1) throws {
try assertTrue((f as AnyObject) is KotlinKSuspendFunction1)
var result: String? = nil
var error: Error? = nil
var completionCalled = 0
f.invoke(p1: "suspend function type") { _result, _error in
completionCalled += 1
result = _result as? String
error = _error
}
try assertEquals(actual: completionCalled, expected: 1)
try assertEquals(actual: result, expected: "suspend function type 1")
try assertNil(error)
}
private func testKSuspendFunctionType() throws {
try testKSuspendFunctionType0(f: CoroutinesKt.getKSuspendCallableReference0(), expectedResult: "callable reference 0")
try testKSuspendFunctionType1(f: CoroutinesKt.getKSuspendCallableReference1())
}
private func testSuspendFunctionSwiftImpl() throws {
var result: String? = nil
var error: Error? = nil
var completionCalled = 0
CoroutinesKt.invoke1(block: SuspendFunction1SwiftImpl(), argument: "suspend function") { _result, _error in
completionCalled += 1
result = _result as? String
error = _error
}
try assertEquals(actual: completionCalled, expected: 1)
try assertEquals(actual: result, expected: "suspend function Swift")
try assertNil(error)
}
#if NO_GENERICS
typealias AnyResultHolder = ResultHolder
#else
typealias AnyResultHolder = ResultHolder<AnyObject>
#endif
private extension AnyResultHolder {
func getSuccessfulResult() throws -> Any? {
try assertEquals(actual: completed, expected: 1)
try assertNil(exception)
return result
}
}
// Reported in https://youtrack.jetbrains.com/issue/KT-51043
private func testSuspendFunction0SwiftImplStartInKotlin() throws {
let resultHolder = AnyResultHolder()
try CoroutinesKt.startCoroutineUninterceptedOrReturn(fn: SuspendFunction0SwiftImpl(), resultHolder: resultHolder)
try assertEquals(actual: resultHolder.getSuccessfulResult() as? String, expected: "Swift")
}
private func testSuspendFunction1SwiftImplStartInKotlin() throws {
let resultHolder = AnyResultHolder()
try CoroutinesKt.startCoroutineUninterceptedOrReturn(fn: SuspendFunction1SwiftImpl(), receiver: "receiver", resultHolder: resultHolder)
try assertEquals(actual: resultHolder.getSuccessfulResult() as? String, expected: "receiver Swift")
}
private func testSuspendFunction2SwiftImplStartInKotlin() throws {
let resultHolder = AnyResultHolder()
try CoroutinesKt.startCoroutineUninterceptedOrReturn(fn: SuspendFunction2SwiftImpl(), receiver: "receiver", param: "param", resultHolder: resultHolder)
try assertEquals(actual: resultHolder.getSuccessfulResult() as? String, expected: "receiver param Swift")
}
private func testSuspendFunction0SwiftImplCreateInKotlin() throws {
let resultHolder = AnyResultHolder()
try CoroutinesKt.createCoroutineUninterceptedAndResume(fn: SuspendFunction0SwiftImpl(), resultHolder: resultHolder)
try assertEquals(actual: resultHolder.getSuccessfulResult() as? String, expected: "Swift")
}
private func testSuspendFunction1SwiftImplCreateInKotlin() throws {
let resultHolder = AnyResultHolder()
try CoroutinesKt.createCoroutineUninterceptedAndResume(fn: SuspendFunction1SwiftImpl(), receiver: "receiver", resultHolder: resultHolder)
try assertEquals(actual: resultHolder.getSuccessfulResult() as? String, expected: "receiver Swift")
}
private class SuspendFunction0SwiftImpl : KotlinSuspendFunction0 {
func invoke(completionHandler: (Any?, Error?) -> Void) {
completionHandler("Swift", nil)
}
}
private class SuspendFunction1SwiftImpl : KotlinSuspendFunction1 {
func invoke(p1: Any?, completionHandler: (Any?, Error?) -> Void) {
completionHandler("\(p1 ?? "nil") Swift", nil)
}
}
private class SuspendFunction2SwiftImpl : KotlinSuspendFunction2 {
func invoke(p1: Any?, p2: Any?, completionHandler: (Any?, Error?) -> Void) {
completionHandler("\(p1 ?? "nil") \(p2 ?? "nil") Swift", nil)
}
}
class CoroutinesTests : SimpleTestProvider {
override init() {
super.init()
test("TestCallSimple", testCallSimple)
test("TestCallUnitSimple", testUnitCallSimple)
test("TestCallFromNonMainDispatcher", testUnitCallNonMainDispatcher)
test("TestCall", testCall)
test("TestCallChain", testCallChain)
test("TestOverride", testOverride)
test("TestBridges", testBridges)
test("TestImplicitThrows1", testImplicitThrows1)
test("TestImplicitThrows2", testImplicitThrows2)
test("TestSuspendFunctionType", testSuspendFunctionType)
test("TestKSuspendFunctionType", testSuspendFunctionType)
test("TestSuspendFunctionSwiftImpl", testSuspendFunctionSwiftImpl)
test("TestSuspendFunction0SwiftImplStartInKotlin", testSuspendFunction0SwiftImplStartInKotlin)
test("TestSuspendFunction1SwiftImplStartInKotlin", testSuspendFunction1SwiftImplStartInKotlin)
test("TestSuspendFunction2SwiftImplStartInKotlin", testSuspendFunction2SwiftImplStartInKotlin)
test("TestSuspendFunction0SwiftImplCreateInKotlin", testSuspendFunction0SwiftImplCreateInKotlin)
test("TestSuspendFunction1SwiftImplCreateInKotlin", testSuspendFunction1SwiftImplCreateInKotlin)
}
}
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package dataClassComponentMethods
data class DataClassWithExplicitComponentMethod(val x: Int, val y: Int) {
fun component1(arg: Int): Int {
return arg + x
}
}
interface ComponentInterface {
fun component1(): Int
}
data class DataClassWithInheritedComponentMethod(val x: Int) : ComponentInterface
class RegularClassWithComponentMethods {
fun component1() = 3
fun component3() = 4
}
fun component1() = 5
fun component4() = 6
data class DataClassWithStrangeNames(val component124: Int, val componentABC: Int) {
operator fun component15() = component124
fun component16() = component124
}
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
private func testCustomComponentMethodsAreAccessible() throws {
let d = DataClassWithExplicitComponentMethod(x: 1, y: 2)
try assertEquals(actual: d.component1(arg: 3), expected: 4)
}
private func testDataClassWithInheritedComponentAreAccessible() throws {
let d = DataClassWithInheritedComponentMethod(x: 1)
try assertEquals(actual: d.component1(), expected: 1)
}
// Absence of deprecation attributes is checked by comparing "lazy header".
private func testRegularComponentMethodsAreAccessible() throws {
let r = RegularClassWithComponentMethods()
try assertEquals(actual: r.component1(), expected: 3)
try assertEquals(actual: r.component3(), expected: 4)
}
private func testTopLevelComponentMethodsAreAccessible() throws {
try assertEquals(actual: DataClassComponentMethodsKt.component1(), expected: 5)
try assertEquals(actual: DataClassComponentMethodsKt.component4(), expected: 6)
}
private func testComponentExportedOrNot() throws {
try assertFalse(class_respondsToSelector(object_getClass(DataClassWithStrangeNames.self), NSSelectorFromString("component1")));
try assertFalse(class_respondsToSelector(object_getClass(DataClassWithStrangeNames.self), NSSelectorFromString("component2")));
try assertFalse(class_respondsToSelector(object_getClass(DataClassWithStrangeNames.self), NSSelectorFromString("component15")));
let r = DataClassWithStrangeNames(component124: 1, componentABC:2)
try assertEquals(actual: r.component124, expected: 1)
try assertEquals(actual: r.componentABC, expected: 2)
try assertEquals(actual: r.component16(), expected: 1)
}
class DataClassComponentMethodsTests : SimpleTestProvider {
override init() {
super.init()
test("testDataClassWithInheritedComponentAreAccessible", testDataClassWithInheritedComponentAreAccessible)
test("testCustomComponentMethodsAreAccessible", testCustomComponentMethodsAreAccessible)
test("testRegularComponentMethodsAreAccessible", testRegularComponentMethodsAreAccessible)
test("testTopLevelComponentMethodsAreAccessible", testTopLevelComponentMethodsAreAccessible)
test("testComponentExportedOrNot", testComponentExportedOrNot)
}
}
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
@file:OptIn(kotlin.experimental.ExperimentalNativeApi::class)
package deallocretain
open class DeallocRetainBase
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
fun garbageCollect() = kotlin.native.runtime.GC.collect()
fun createWeakReference(value: Any) = kotlin.native.ref.WeakReference(value)
fun assertNull(value: Any?) {
kotlin.test.assertNull(value)
}
@OptIn(kotlin.ExperimentalStdlibApi::class)
fun isExperimentalMM() = kotlin.native.isExperimentalMM()
@@ -0,0 +1,109 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
// Note: these tests rely on GC assertions: without the fix and the assertions it won't actually crash.
// GC should fire an assertion if it obtains a reference to Kotlin object that is being (or has been) deallocated.
private func test1() throws {
// Attempt to make the state predictable:
DeallocRetainKt.garbageCollect()
DeallocRetain.deallocated = false
try assertFalse(DeallocRetain.deallocated)
try autoreleasepool {
let obj = DeallocRetain()
try obj.checkWeak()
}
// Runs DeallocRetain.deinit:
DeallocRetainKt.garbageCollect()
try assertTrue(DeallocRetain.deallocated)
// Might crash due to double-dispose if the dealloc applied addRef/releaseRef to reclaimed Kotlin object:
DeallocRetainKt.garbageCollect()
}
private class DeallocRetain : DeallocRetainBase {
static var deallocated = false
static var retainObject: DeallocRetain? = nil
static weak var weakObject: DeallocRetain? = nil
#if NO_GENERICS
static var kotlinWeakRef: KotlinWeakReference? = nil
#else
static var kotlinWeakRef: KotlinWeakReference<AnyObject>? = nil
#endif
override init() {
super.init()
DeallocRetain.weakObject = self
DeallocRetain.kotlinWeakRef = DeallocRetainKt.createWeakReference(value: self)
}
func checkWeak() throws {
try assertSame(actual: DeallocRetain.weakObject, expected: self)
try assertSame(actual: DeallocRetain.kotlinWeakRef!.value as AnyObject, expected: self)
}
deinit {
DeallocRetain.retainObject = self
DeallocRetain.retainObject = nil
try! assertNil(DeallocRetain.weakObject)
try! assertNil(DeallocRetain.kotlinWeakRef!.value)
try! assertFalse(DeallocRetain.deallocated)
DeallocRetain.deallocated = true
}
}
private class DeallocRetainAndAccess : DeallocRetainBase {
static var deallocated = false
static var retainObject: DeallocRetainAndAccess? = nil
deinit {
DeallocRetainAndAccess.retainObject = self
DeallocRetainKt.assertNull(value: DeallocRetainAndAccess.retainObject)
DeallocRetainAndAccess.retainObject = nil
try! assertFalse(DeallocRetainAndAccess.deallocated)
DeallocRetainAndAccess.deallocated = true
}
}
private func test2() throws {
// Attempt to make the state predictable:
DeallocRetainKt.garbageCollect()
DeallocRetainAndAccess.deallocated = false
autoreleasepool {
DeallocRetainAndAccess()
}
// Runs DeallocRetainAndAccess.deinit:
DeallocRetainKt.garbageCollect()
try assertTrue(DeallocRetain.deallocated)
// Might crash due to double-dispose if the dealloc applied addRef/releaseRef to reclaimed Kotlin object:
DeallocRetainKt.garbageCollect()
}
class DeallocRetainTests : SimpleTestProvider {
override init() {
super.init()
#if !NOOP_GC
test("Test1", test1)
if (DeallocRetainKt.isExperimentalMM()) {
test("Test2", test2)
}
#endif
}
}
@@ -0,0 +1,23 @@
package enumValues
import noEnumEntries.*
enum class EnumLeftRightUpDown {
LEFT, RIGHT, UP, DOWN
}
enum class EnumOneTwoThreeValues {
ONE, TWO, THREE, VALUES, ENTRIES
}
enum class EnumValuesValues_ {
VALUES, VALUES_, ENTRIES, ENTRIES_
}
enum class EmptyEnum {
}
fun dceAvoidance() : NoEnumEntriesEnum {
return NoEnumEntriesEnum.ONE
}
@@ -0,0 +1,118 @@
import Kt
private func testEnumValues() throws {
let values = EnumLeftRightUpDown.values()
try assertEquals(actual: values.size, expected: 4)
try assertSame(actual: values.get(index: 0) as AnyObject, expected: EnumLeftRightUpDown.left)
try assertSame(actual: values.get(index: 1) as AnyObject, expected: EnumLeftRightUpDown.right)
try assertSame(actual: values.get(index: 2) as AnyObject, expected: EnumLeftRightUpDown.up)
try assertSame(actual: values.get(index: 3) as AnyObject, expected: EnumLeftRightUpDown.down)
}
private func testEnumValuesMangled() throws {
let values = EnumOneTwoThreeValues.values_()
try assertEquals(actual: values.size, expected: 5)
try assertSame(actual: values.get(index: 0) as AnyObject, expected: EnumOneTwoThreeValues.one)
try assertSame(actual: values.get(index: 1) as AnyObject, expected: EnumOneTwoThreeValues.two)
try assertSame(actual: values.get(index: 2) as AnyObject, expected: EnumOneTwoThreeValues.three)
try assertSame(actual: values.get(index: 3) as AnyObject, expected: EnumOneTwoThreeValues.values)
try assertSame(actual: values.get(index: 4) as AnyObject, expected: EnumOneTwoThreeValues.entries)
}
private func testEnumValuesMangledTwice() throws {
let values = EnumValuesValues_.values__()
try assertEquals(actual: values.size, expected: 4)
try assertSame(actual: values.get(index: 0) as AnyObject, expected: EnumValuesValues_.values)
try assertSame(actual: values.get(index: 1) as AnyObject, expected: EnumValuesValues_.values_)
try assertSame(actual: values.get(index: 2) as AnyObject, expected: EnumValuesValues_.entries)
try assertSame(actual: values.get(index: 3) as AnyObject, expected: EnumValuesValues_.entries_)
}
private func testEnumValuesEmpty() throws {
try assertEquals(actual: EmptyEnum.values().size, expected: 0)
}
extension NSObject {
// convert to dictionary
static func toDictionary(from classType: AnyClass) -> [String: Any] {
var propertiesCount : CUnsignedInt = 0
let propertiesInAClass = class_copyMethodList(classType, &propertiesCount)
var propertiesDictionary = [String:Any]()
for i in 0 ..< Int(propertiesCount) {
if let property = propertiesInAClass?[i],
let strKey = NSString(utf8String: sel_getName(method_getName(property))) as String? {
propertiesDictionary[strKey] = value(forKey: strKey)
}
}
return propertiesDictionary
}
}
private func testNoEnumEntries() throws {
try assertTrue(class_respondsToSelector(object_getClass(EnumLeftRightUpDown.self), NSSelectorFromString("entries")));
try assertFalse(class_respondsToSelector(object_getClass(NoEnumEntriesEnum.self), NSSelectorFromString("entries")));
}
private func testEnumEntries() throws {
let entries = EnumLeftRightUpDown.entries
try assertEquals(actual: entries.count, expected: 4)
try assertSame(actual: entries[0] as AnyObject, expected: EnumLeftRightUpDown.left)
try assertSame(actual: entries[1] as AnyObject, expected: EnumLeftRightUpDown.right)
try assertSame(actual: entries[2] as AnyObject, expected: EnumLeftRightUpDown.up)
try assertSame(actual: entries[3] as AnyObject, expected: EnumLeftRightUpDown.down)
}
private func testEnumEntriesMangled() throws {
let entries = EnumOneTwoThreeValues.entries_
try assertEquals(actual: entries.count, expected: 5)
try assertSame(actual: entries[0] as AnyObject, expected: EnumOneTwoThreeValues.one)
try assertSame(actual: entries[1] as AnyObject, expected: EnumOneTwoThreeValues.two)
try assertSame(actual: entries[2] as AnyObject, expected: EnumOneTwoThreeValues.three)
try assertSame(actual: entries[3] as AnyObject, expected: EnumOneTwoThreeValues.values)
try assertSame(actual: entries[4] as AnyObject, expected: EnumOneTwoThreeValues.entries)
}
private func testEnumEntriesMangledTwice() throws {
let entries = EnumValuesValues_.entries__
try assertEquals(actual: entries.count, expected: 4)
try assertSame(actual: entries[0] as AnyObject, expected: EnumValuesValues_.values)
try assertSame(actual: entries[1] as AnyObject, expected: EnumValuesValues_.values_)
try assertSame(actual: entries[2] as AnyObject, expected: EnumValuesValues_.entries)
try assertSame(actual: entries[3] as AnyObject, expected: EnumValuesValues_.entries_)
}
private func testEnumEntriesEmpty() throws {
try assertEquals(actual: EmptyEnum.entries.count, expected: 0)
}
class EnumValuesTests : SimpleTestProvider {
override init() {
super.init()
test("TestEnumValues", testEnumValues)
test("TestEnumValuesMangled", testEnumValuesMangled)
test("TestEnumValuesMangledTwice", testEnumValuesMangledTwice)
test("TestEnumValuesEmpty", testEnumValuesEmpty)
test("TestNoEnumEntries", testNoEnumEntries)
test("TestEnumEntries", testEnumEntries)
test("TestEnumEntriesMangled", testEnumEntriesMangled)
test("TestEnumEntriesMangledTwice", testEnumEntriesMangledTwice)
test("TestEnumEntriesEmpty", testEnumEntriesEmpty)
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,15 @@
package funinterfaces
fun interface FunInterface {
fun run(): Int
}
fun getObject(): FunInterface {
return object : FunInterface {
override fun run() = 1
}
}
fun getLambda(): FunInterface {
return FunInterface { 2 }
}
@@ -0,0 +1,15 @@
import Kt
// Based on https://youtrack.jetbrains.com/issue/KT-44799.
private func testSAMConversion() throws {
try assertEquals(actual: FunInterfacesKt.getObject().run(), expected: 1)
try assertEquals(actual: FunInterfacesKt.getLambda().run(), expected: 2)
}
class FunInterfacesTests : SimpleTestProvider {
override init() {
super.init()
test("TestSAMConversion", testSAMConversion)
}
}
@@ -0,0 +1,125 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package functionalTypes
import kotlin.test.*
typealias AN = Any?
typealias F2 = (AN, AN) -> AN
typealias F5 = (AN, AN, AN, AN, AN) -> AN
typealias F6 = (AN, AN, AN, AN, AN, AN,) -> AN
typealias F32 = (AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN,
AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN,
AN, AN, AN, AN, AN, AN, AN, AN) -> AN
typealias F33 = (AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN,
AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN, AN,
AN, AN, AN, AN, AN, AN, AN, AN, AN) -> AN
fun callDynType2(list: List<F2>, param: AN) {
val fct = list.first()
val ret = fct(param, null)
assertEquals(param, ret)
}
fun callStaticType2(fct: F2, param: AN) {
val ret = fct(param, null)
assertEquals(param, ret)
}
fun callDynType32(list: List<F32>, param: AN) {
val fct = list.first()
val ret = fct(param
, null, null, null, null, null, null, null
, null, null, null, null, null, null, null, null
, null, null, null, null, null, null, null, null
, null, null, null, null, null, null, null, null
)
assertEquals(param, ret)
}
fun callStaticType32(fct: F32, param: AN) {
val ret = fct(param
, null, null, null, null, null, null, null
, null, null, null, null, null, null, null, null
, null, null, null, null, null, null, null, null
, null, null, null, null, null, null, null, null
)
assertEquals(param, ret)
}
fun callDynType33(list: List<F33>, param: AN) {
val fct = list.first()
val ret = fct(param
, null, null, null, null, null, null, null
, null, null, null, null, null, null, null, null
, null, null, null, null, null, null, null, null
, null, null, null, null, null, null, null, null, null
)
assertEquals(param, ret)
}
fun callStaticType33(fct: F33, param: AN) {
val ret = fct(param
, null, null, null, null, null, null, null
, null, null, null, null, null, null, null, null
, null, null, null, null, null, null, null, null
, null, null, null, null, null, null, null, null, null
)
assertEquals(param, ret)
}
abstract class FHolder {
abstract val value: Any?
}
// Note: can't provoke dynamic function type conversion using list (as above) or generics
// due to Swift <-> Obj-C interop bugs/limitations.
// Use covariant return type instead:
class F2Holder(override val value: F2) : FHolder()
fun getDynTypeLambda2(): F2Holder = F2Holder({ p1, _ -> p1 })
fun getStaticLambda2(): F2 = { p1, _ -> p1 }
private fun f2(p1: AN, p2: AN): AN = p1
fun getDynTypeRef2(): F2Holder = F2Holder(::f2)
fun getStaticRef2(): F2 = ::f2
private fun f32(
p1: AN, p2: AN, p3: AN, p4: AN, p5: AN, p6: AN, p7: AN, p8: AN,
p9: AN, p10: AN, p11: AN, p12: AN, p13: AN, p14: AN, p15: AN, p16: AN,
p17: AN, p18: AN, p19: AN, p20: AN, p21: AN, p22: AN, p23: AN, p24: AN,
p25: AN, p26: AN, p27: AN, p28: AN, p29: AN, p30: AN, p31: AN, p32: AN
): AN = p1
private fun f33(
p1: AN, p2: AN, p3: AN, p4: AN, p5: AN, p6: AN, p7: AN, p8: AN,
p9: AN, p10: AN, p11: AN, p12: AN, p13: AN, p14: AN, p15: AN, p16: AN,
p17: AN, p18: AN, p19: AN, p20: AN, p21: AN, p22: AN, p23: AN, p24: AN,
p25: AN, p26: AN, p27: AN, p28: AN, p29: AN, p30: AN, p31: AN, p32: AN,
p33: AN
): AN = p1
class F32Holder(override val value: F32) : FHolder()
fun getDynType32(): F32Holder = F32Holder(::f32)
fun getStaticType32(): F32 = ::f32
class F33Holder(override val value: F33) : FHolder()
fun getDynTypeRef33(): F33Holder = F33Holder(::f33)
fun getStaticTypeRef33(): F33 = ::f33
fun getDynTypeLambda33(): F33Holder = F33Holder(getStaticTypeLambda33())
fun getStaticTypeLambda33(): F33 = {
p,
_, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _
->
p
}
@@ -0,0 +1,145 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
private func test1() {
FunctionalTypesKt.callStaticType2(fct: foo2, param: "from swift")
FunctionalTypesKt.callDynType2(list: [ foo2 ], param: "from swift")
FunctionalTypesKt.callStaticType2(fct : {a1, _ in return a1 }, param: "from swift block")
FunctionalTypesKt.callDynType2(list: [ {a1, _ in return a1 } ], param: "from swift block")
// 32 params is mapped as regular; block is OK
FunctionalTypesKt.callStaticType32(fct : {
a1, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _
in return a1 }, param: "from swift block")
FunctionalTypesKt.callDynType32(list : [{
a1, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _
in return a1 }], param: "from swift block")
// 33 params requires explicit implementation of KotlinFunction33
FunctionalTypesKt.callStaticType33(fct: foo33, param: "from swift")
FunctionalTypesKt.callDynType33(list: [ Foo33() ], param: "from swift")
}
private func test2() throws {
try assertEquals(actual: FunctionalTypesKt.getDynTypeLambda2().value("one", nil) as? String, expected: "one")
try assertEquals(actual: FunctionalTypesKt.getStaticLambda2()("two", nil) as? String, expected: "two")
try assertEquals(actual: FunctionalTypesKt.getDynTypeRef2().value("three", nil) as? String, expected: "three")
try assertEquals(actual: FunctionalTypesKt.getStaticRef2()("four", nil) as? String, expected: "four")
// 32 params is mapped as regular; calling result as block is OK
try assertEquals(
actual: FunctionalTypesKt.getDynType32().value(
"five",
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil
) as? String,
expected: "five"
)
try assertEquals(
actual: FunctionalTypesKt.getStaticType32()(
"six",
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil
) as? String,
expected: "six"
)
// 33 params requires explicit invocation of KotlinFunction33.invoke
try assertEquals(
actual: FunctionalTypesKt.getDynTypeRef33().value.invoke(
p1: "seven",
p2: nil, p3: nil, p4: nil, p5: nil, p6: nil, p7: nil, p8: nil, p9: nil,
p10: nil, p11: nil, p12: nil, p13: nil, p14: nil, p15: nil, p16: nil, p17: nil,
p18: nil, p19: nil, p20: nil, p21: nil, p22: nil, p23: nil, p24: nil, p25: nil,
p26: nil, p27: nil, p28: nil, p29: nil, p30: nil, p31: nil, p32: nil, p33: nil
) as? String,
expected: "seven"
)
// static conversion is ok though.
try assertEquals(
actual: FunctionalTypesKt.getStaticTypeRef33()(
"eight",
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil
) as? String,
expected: "eight"
)
try assertEquals(
actual: FunctionalTypesKt.getDynTypeLambda33().value.invoke(
p1: "nine",
p2: nil, p3: nil, p4: nil, p5: nil, p6: nil, p7: nil, p8: nil, p9: nil,
p10: nil, p11: nil, p12: nil, p13: nil, p14: nil, p15: nil, p16: nil, p17: nil,
p18: nil, p19: nil, p20: nil, p21: nil, p22: nil, p23: nil, p24: nil, p25: nil,
p26: nil, p27: nil, p28: nil, p29: nil, p30: nil, p31: nil, p32: nil, p33: nil
) as? String,
expected: "nine"
)
try assertEquals(
actual: FunctionalTypesKt.getStaticTypeLambda33()(
"ten",
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, nil, nil, nil, nil, nil, nil
) as? String,
expected: "ten"
)
}
class FunctionalTypesTests : SimpleTestProvider {
override init() {
super.init()
test("Test1", test1)
test("Test2", test2)
}
}
private func foo2(a1: Any?, _: Any?) -> Any? {
return a1
}
private func foo33(a1: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?,
_: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?,
_: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?,
_: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?, _: Any?
) -> Any? {
return a1
}
private class Foo33 : KotlinFunction33 {
func invoke(p1: Any?, p2: Any?, p3: Any?, p4: Any?, p5: Any?, p6: Any?, p7: Any?, p8: Any?, p9: Any?,
p10: Any?, p11: Any?, p12: Any?, p13: Any?, p14: Any?, p15: Any?, p16: Any?, p17: Any?, p18: Any?, p19: Any?,
p20: Any?, p21: Any?, p22: Any?, p23: Any?, p24: Any?, p25: Any?, p26: Any?, p27: Any?, p28: Any?, p29: Any?,
p30: Any?, p31: Any?, p32: Any?, p33: Any?
) -> Any? {
return foo33(a1: p1
, nil, nil, nil, nil, nil, nil, nil, nil
, nil, nil, nil, nil, nil, nil, nil, nil
, nil, nil, nil, nil, nil, nil, nil, nil
, nil, nil, nil, nil, nil, nil, nil, nil)
}
}
@@ -0,0 +1,9 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package gh4002
open class GH4002ArgumentBase
class GH4002Argument : GH4002ArgumentBase()
@@ -0,0 +1,31 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
// See https://github.com/JetBrains/kotlin-native/issues/4002
class GH4002Base0 : NSObject, NSCoding {
required init(coder: NSCoder) { fatalError() }
func encode(with coder: NSCoder) { fatalError() }
}
class GH4002Base1<T : GH4002ArgumentBase> : GH4002Base0 {}
@objc(ObjCGH4002)
class GH4002 : GH4002Base1<GH4002Argument> {}
private func test1() throws {
try assertEquals(actual: String(cString: class_getName(GH4002.self)), expected: "ObjCGH4002")
}
class Gh4002Tests : SimpleTestProvider {
override init() {
super.init()
test("Test1", test1)
}
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package headerWarnings
// Note: the test parses the generated header with -Werror to detect warnings.
class TestIncompatiblePropertyTypeWarning {
class Generic<T>(val value: T)
interface InterfaceWithGenericProperty<T> {
val p: Generic<T>
}
class ClassOverridingInterfaceWithGenericProperty(override val p: Generic<String>) : InterfaceWithGenericProperty<String>
}
// https://github.com/JetBrains/kotlin-native/issues/3992
class TestGH3992 {
abstract class C(open val a: A)
class D(override val a: B) : C(a)
abstract class A
class B : A()
}
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
// Note: the test parses the generated header with -Werror to detect warnings.
// It is enough to have just Kotlin declarations at the moment.
// Adding usages for all declarations to avoid any kind of DCE that may appear later.
#if !NO_GENERICS
private func testIncompatiblePropertyType() throws {
let c = TestIncompatiblePropertyTypeWarning.ClassOverridingInterfaceWithGenericProperty(
p: TestIncompatiblePropertyTypeWarningGeneric<NSString>(value: "cba")
)
let pc: TestIncompatiblePropertyTypeWarningGeneric<NSString> = c.p
try assertEquals(actual: pc.value, expected: "cba")
let i: TestIncompatiblePropertyTypeWarningInterfaceWithGenericProperty = c
let pi: TestIncompatiblePropertyTypeWarningGeneric<AnyObject> = i.p
try assertEquals(actual: pi.value as! String, expected: "cba")
}
#endif
private func testGH3992() throws {
let d = TestGH3992.D(a: TestGH3992.B())
let c: TestGH3992.C = d
let b: TestGH3992.B = d.a
let a: TestGH3992.A = b
try assertTrue(a is TestGH3992.B)
}
class HeaderWarningsTests : SimpleTestProvider {
override init() {
super.init()
#if !NO_GENERICS
test("TestIncompatiblePropertyType", testIncompatiblePropertyType)
#endif
test("TestGH3992", testGH3992)
}
}
@@ -0,0 +1,132 @@
/*
* Copyright 2010-2023 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 hiddenfromobjc
import kotlin.experimental.ExperimentalObjCRefinement
@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
data class ClassNotAvailableInSwift(val param: String)
// KT-58839
fun ClassNotAvailableInSwift.doSomethingMeaningless(another: ClassNotAvailableInSwift): ClassNotAvailableInSwift {
return ClassNotAvailableInSwift(this.param + another.param)
}
fun String.doSomethingMeaningless(another: ClassNotAvailableInSwift): ClassNotAvailableInSwift {
return ClassNotAvailableInSwift(this + another.param)
}
// Check that inner and nested classes are hidden if enclosing class is hidden
@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
class ParentClass {
class NestedClass {
class DeeplyNestedClass
}
inner class InnerClass
}
fun useOfUnavailableClass(param: ClassNotAvailableInSwift): ClassNotAvailableInSwift {
return ClassNotAvailableInSwift("hi")
}
fun useOfNullableUnavailableClass(param: ClassNotAvailableInSwift?): ClassNotAvailableInSwift? {
return null
}
fun produceUnavailable(): ClassNotAvailableInSwift {
return ClassNotAvailableInSwift("hi")
}
fun consumeUnavailable(param: ClassNotAvailableInSwift): String {
return param.param
}
@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
interface InterfaceNotAvailableInSwift {
fun f(): String
}
fun createUnavailableInterface(): InterfaceNotAvailableInSwift {
return object : InterfaceNotAvailableInSwift {
override fun f(): String = "I'm actually unavailable, call me later."
}
}
fun useOfNullableUnavailableInterface(param: InterfaceNotAvailableInSwift?): String? {
return param?.f() ?: "null"
}
@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
enum class UnavailableEnum {
A, B, C;
}
fun createUnavailableEnum(): UnavailableEnum {
return UnavailableEnum.A
}
fun useOfUnavailableEnum(param: UnavailableEnum): String {
return param.toString()
}
fun useOfNullableUnavailableEnum(param: UnavailableEnum?): String {
return param?.toString() ?: "null"
}
@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
object UnavailableObject {
val field: String = "objectField"
}
fun getUnavailableObject(): UnavailableObject {
return UnavailableObject
}
fun useOfUnavailableObject(param:UnavailableObject):String {
return param.field
}
fun useOfNullableUnavailableObject(param:UnavailableObject?):String? {
return param?.field ?: "null"
}
sealed class SealedClass {
@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
class A : SealedClass()
class B : SealedClass()
@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
object C : SealedClass()
}
fun createSealedClass(): SealedClass {
return SealedClass.A()
}
fun useSealedClass(param: SealedClass): String {
return when (param) {
is SealedClass.A -> "A"
is SealedClass.B -> "B"
SealedClass.C -> "C"
}
}
fun <T : InterfaceNotAvailableInSwift> useUnavailable(a : T): String {
return a.f()
}
class WrapperOverUnavailable<T: InterfaceNotAvailableInSwift>(val arg: T)
@@ -0,0 +1,58 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
private func testUnavailableEnum() throws {
try assertEquals(actual: HiddenfromobjcKt.useOfUnavailableEnum(param: HiddenfromobjcKt.createUnavailableEnum()), expected: "A")
try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableEnum(param: nil), expected: "null")
try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableEnum(param: HiddenfromobjcKt.createUnavailableEnum()), expected: "A")
}
private func testUnavailableObject() throws {
try assertEquals(actual: HiddenfromobjcKt.useOfUnavailableObject(param: HiddenfromobjcKt.getUnavailableObject()), expected: "objectField")
try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableObject(param: HiddenfromobjcKt.getUnavailableObject()), expected: "objectField")
try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableObject(param: nil), expected: "null")
}
private func testUnavailableInterface() throws {
try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableInterface(
param: HiddenfromobjcKt.createUnavailableInterface()),
expected: "I'm actually unavailable, call me later."
)
try assertEquals(actual: HiddenfromobjcKt.useOfNullableUnavailableInterface(param: nil), expected: "null")
}
private func testSealedClass() throws {
try assertEquals(actual: HiddenfromobjcKt.useSealedClass(param: HiddenfromobjcKt.createSealedClass()), expected: "A")
try assertEquals(actual: HiddenfromobjcKt.useSealedClass(param: SealedClass.B()), expected: "B")
}
private func testUnavailableGenerics() throws {
try assertEquals(
actual: HiddenfromobjcKt.useUnavailable(a: HiddenfromobjcKt.createUnavailableInterface()),
expected: "I'm actually unavailable, call me later."
)
let wrapper = WrapperOverUnavailable(arg: HiddenfromobjcKt.createUnavailableInterface() as AnyObject)
try assertEquals(
actual: HiddenfromobjcKt.useUnavailable(a: wrapper.arg),
expected: "I'm actually unavailable, call me later."
)
}
class HiddenfromobjcTests : SimpleTestProvider {
override init() {
super.init()
// Here we check that even if type is erased from Objective-C declarations, we still able to use them properly with proper objects.
test("testUnavailableEnum", testUnavailableEnum)
test("testUnavailableObject", testUnavailableObject)
test("testUnavailableInterface", testUnavailableInterface)
test("testSealedClass", testSealedClass)
test("testUnavailableGenerics", testUnavailableGenerics)
}
}
@@ -0,0 +1,73 @@
@file:OptIn(kotlin.experimental.ExperimentalObjCName::class)
package objcNameMangling
interface InterfaceNameManglingI1 {
val clashingProperty: Int
fun clashingMethod(): Int
@ObjCName(name = "interfaceClashingMethodWithObjCNameInI1")
fun clashingMethodWithObjCNameInI1(): Int
fun interfaceClashingMethodWithObjCNameInI2(): Int
@ObjCName(name = "interfaceClashingMethodWithObjCNameInBoth")
fun clashingMethodWithObjCNameInBoth(): Int
}
fun i1() = object : InterfaceNameManglingI1 {
override val clashingProperty: Int
get() = 1
override fun clashingMethod(): Int = 2
override fun clashingMethodWithObjCNameInI1(): Int = 3
override fun interfaceClashingMethodWithObjCNameInI2(): Int = 4
override fun clashingMethodWithObjCNameInBoth(): Int = 5
}
interface InterfaceNameManglingI2 {
val clashingProperty: Any
fun clashingMethod(): Any
fun interfaceClashingMethodWithObjCNameInI1(): Any
@ObjCName(name = "interfaceClashingMethodWithObjCNameInI2")
fun clashingMethodWithObjCNameInI2(): Any
@ObjCName(name = "interfaceClashingMethodWithObjCNameInBoth")
fun clashingMethodWithObjCNameInBoth(): Any
}
fun i2() = object : InterfaceNameManglingI2 {
override val clashingProperty: Any
get() = "one"
override fun clashingMethod(): Any = "two"
override fun interfaceClashingMethodWithObjCNameInI1(): Any = "three"
override fun clashingMethodWithObjCNameInI2(): Any = "four"
override fun clashingMethodWithObjCNameInBoth(): Any = "five"
}
class InterfaceNameManglingC1 {
val clashingProperty: String = "one"
fun clashingMethod(): String = "two"
}
final class InterfaceNameManglingC2 {
val clashingProperty: Int = 1
fun clashingMethod(): Int = 2
}
fun o1() = InterfaceNameManglingC1()
fun o2() = InterfaceNameManglingC2()
@@ -0,0 +1,35 @@
import Kt
private func test1() throws {
let i1 = InterfaceMethodNameManglingKt.i1()
let i2 = InterfaceMethodNameManglingKt.i2()
let o1 = InterfaceMethodNameManglingKt.o1()
let o2 = InterfaceMethodNameManglingKt.o2()
#if DISABLE_MEMBER_NAME_MANGLING || DISABLE_INTERFACE_METHOD_NAME_MANGLING
try assertEquals(actual: i1.clashingProperty, expected: 1)
try assertEquals(actual: i1.clashingMethod(), expected: 2)
try assertEquals(actual: i1.interfaceClashingMethodWithObjCNameInI1(), expected: 3)
try assertEquals(actual: i1.interfaceClashingMethodWithObjCNameInI2(), expected: 4)
try assertEquals(actual: i1.interfaceClashingMethodWithObjCNameInBoth(), expected: 5)
try assertEquals(actual: i2.clashingProperty as! String, expected: "one")
try assertEquals(actual: i2.clashingMethod() as! String, expected: "two")
try assertEquals(actual: i2.interfaceClashingMethodWithObjCNameInI1() as! String, expected: "three")
try assertEquals(actual: i2.interfaceClashingMethodWithObjCNameInI2() as! String, expected: "four")
try assertEquals(actual: i2.interfaceClashingMethodWithObjCNameInBoth() as! String, expected: "five")
try assertEquals(actual: o1.clashingProperty, expected: "one")
try assertEquals(actual: o1.clashingMethod(), expected: "two")
#endif
try assertEquals(actual: o2.clashingProperty, expected: 1)
try assertEquals(actual: o2.clashingMethod(), expected: 2)
}
class InterfaceMethodNameManglingTests : SimpleTestProvider {
override init() {
super.init()
test("Test1", test1)
}
}
@@ -0,0 +1,80 @@
/*
* Copyright 2010-2021 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 kdocExport
/**
* Summary class [KDocExport].
*
* @property xyzzy Doc for property xyzzy
* @property zzz See below.
*/
// Expected: this comment shall not affect KDoc (i.e. kdoc above is still OK)
class KDocExport() {
/**
* @param xyzzy is documented.
*
* This is multi-line KDoc. See a blank line above.
*/
val xyzzy: String = "String example"
/** Non-primary ctor KDoc: */
constructor(name: String) : this() {
println(name)
}
/** @property xyzzy KDoc for foo? */
val foo = "foo"
/** @property foo KDoc for yxxyz? */
var yxxyz = 0;
}
/**
* Useless function [whatever]
*
* This kdoc has some additional formatting.
* @param a keep intact and return
* @return value of [a]
* Check for additional comment (note) below
*/
@Throws(IllegalArgumentException::class)
fun whatever(a:String) = a
public abstract class SomeClassWithProperty
{
/**
* Returns dispatcher that executes coroutines immediately when it is already in the right context
* (e.g. current looper is the same as this handler's looper) without an additional [re-dispatch][CoroutineDispatcher.dispatch].
*
* Immediate dispatcher is safe from stack overflows and in case of nested invocations forms event-loop similar to [Dispatchers.Unconfined].
* The event loop is an advanced topic and its implications can be found in [Dispatchers.Unconfined] documentation.
* The formed event-loop is shared with [Unconfined] and other immediate dispatchers, potentially overlapping tasks between them.
*
* Example of usage:
* ```
* suspend fun updateUiElement(val text: String) {
* /*
* * If it is known that updateUiElement can be invoked both from the Main thread and from other threads,
* * `immediate` dispatcher is used as a performance optimization to avoid unnecessary dispatch.
* *
* * In that case, when `updateUiElement` is invoked from the Main thread, `uiElement.text` will be
* * invoked immediately without any dispatching, otherwise, the `Dispatchers.Main` dispatch cycle will be triggered.
* */
* withContext(Dispatchers.Main.immediate) {
* uiElement.text = text
* }
* // Do context-independent logic such as logging
* }
* ```
*
* Method may throw [UnsupportedOperationException] if immediate dispatching is not supported by current dispatcher,
* please refer to specific dispatcher documentation.
*
* [Dispatchers.Main] supports immediate execution for Android, JavaFx and Swing platforms.
*/
public abstract val heavyFormattedKDocFoo: SomeClassWithProperty
}
@@ -0,0 +1,81 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package kotlinPrivateOverride
import kotlin.test.*
// The intention is to test "virtual adapters" machinery of ObjCExport.
// This machinery handles the case when exported Kotlin type is subclassed
// by a non-exported (e.g. private) Kotlin type, and the instance of the latter is passed to Obj-C.
interface KotlinPrivateOverrideI1 {
fun i123AbstractMethod(): Int
fun i1OpenMethod(): Int = -1
}
interface KotlinPrivateOverrideI2 {
fun i123AbstractMethod(): Int
fun i234AbstractMethod(): Int
fun i2AbstractMethod(): Int
}
private interface KotlinPrivateOverridePI1 {
fun pi1AbstractMethod(): Int
}
abstract class KotlinPrivateOverrideA1 : KotlinPrivateOverrideI1, KotlinPrivateOverrideI2, KotlinPrivateOverridePI1 {
abstract fun a1AbstractMethod(): Int
open fun a1OpenMethod(): Int = -2
}
interface KotlinPrivateOverrideI3 {
fun i123AbstractMethod(): Int
fun i234AbstractMethod(): Int
fun i3AbstractMethod(): Int
}
private interface KotlinPrivateOverridePI2 {
fun pi2AbstractMethod(): Int
}
private open class KotlinPrivateOverrideP1 : KotlinPrivateOverrideA1(), KotlinPrivateOverrideI3, KotlinPrivateOverridePI2 {
override fun i123AbstractMethod(): Int = 1
override fun i1OpenMethod(): Int = 2
override fun i234AbstractMethod(): Int = 3
override fun i2AbstractMethod(): Int = 4
override fun pi1AbstractMethod(): Int = 5
override fun a1AbstractMethod(): Int = 6
override fun a1OpenMethod(): Int = 7
override fun i3AbstractMethod(): Int = 8
override fun pi2AbstractMethod(): Int = 9
}
fun createP1(): Any = KotlinPrivateOverrideP1()
interface KotlinPrivateOverrideI4 {
fun i234AbstractMethod(): Int
fun i4AbstractMethod(): Int
}
private interface KotlinPrivateOverridePI3 {
fun pi3AbstractMethod(): Int
}
private class KotlinPrivateOverrideP12 : KotlinPrivateOverrideP1(), KotlinPrivateOverrideI4, KotlinPrivateOverridePI3 {
override fun i123AbstractMethod(): Int = 11
override fun i1OpenMethod(): Int = 12
override fun i234AbstractMethod(): Int = 13
override fun i2AbstractMethod(): Int = 14
override fun pi1AbstractMethod(): Int = 15
override fun a1AbstractMethod(): Int = 16
override fun a1OpenMethod(): Int = 17
override fun i3AbstractMethod(): Int = 18
override fun pi2AbstractMethod(): Int = 19
override fun i4AbstractMethod(): Int = 20
override fun pi3AbstractMethod(): Int = 21
}
fun createP12(): Any = KotlinPrivateOverrideP12()
@@ -0,0 +1,66 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
private func testI1Methods(p: Any, base: Int32) throws {
guard let i1 = p as? KotlinPrivateOverrideI1 else { try fail() }
try assertEquals(actual: i1.i123AbstractMethod(), expected: base + 1)
try assertEquals(actual: i1.i1OpenMethod(), expected: base + 2)
}
private func testI2Methods(p: Any, base: Int32) throws {
guard let i2 = p as? KotlinPrivateOverrideI2 else { try fail() }
try assertEquals(actual: i2.i123AbstractMethod(), expected: base + 1)
try assertEquals(actual: i2.i234AbstractMethod(), expected: base + 3)
try assertEquals(actual: i2.i2AbstractMethod(), expected: base + 4)
}
private func testA1Methods(p: Any, base: Int32) throws {
guard let a1 = p as? KotlinPrivateOverrideA1 else { try fail() }
try assertEquals(actual: a1.i123AbstractMethod(), expected: base + 1)
try assertEquals(actual: a1.i1OpenMethod(), expected: base + 2)
try assertEquals(actual: a1.i234AbstractMethod(), expected: base + 3)
try assertEquals(actual: a1.i2AbstractMethod(), expected: base + 4)
try assertEquals(actual: a1.a1AbstractMethod(), expected: base + 6)
try assertEquals(actual: a1.a1OpenMethod(), expected: base + 7)
}
private func testI3Methods(p: Any, base: Int32) throws {
guard let i3 = p as? KotlinPrivateOverrideI3 else { try fail() }
try assertEquals(actual: i3.i123AbstractMethod(), expected: base + 1)
try assertEquals(actual: i3.i234AbstractMethod(), expected: base + 3)
try assertEquals(actual: i3.i3AbstractMethod(), expected: base + 8)
}
private func testI4Methods(p: Any, base: Int32) throws {
guard let i4 = p as? KotlinPrivateOverrideI4 else { try fail() }
try assertEquals(actual: i4.i234AbstractMethod(), expected: base + 3)
try assertEquals(actual: i4.i4AbstractMethod(), expected: base + 10)
}
private func test(p: Any, base: Int32, isI4: Bool) throws {
try testI1Methods(p: p, base: base)
try testI2Methods(p: p, base: base)
try testA1Methods(p: p, base: base)
try testI3Methods(p: p, base: base)
if isI4 {
try testI4Methods(p: p, base: base)
}
}
private func test1() throws {
try test(p: KotlinPrivateOverrideKt.createP1(), base: 0, isI4: false)
try test(p: KotlinPrivateOverrideKt.createP12(), base: 10, isI4: true)
}
class KotlinPrivateOverrideTests : SimpleTestProvider {
override init() {
super.init()
test("Test1", test1)
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package kt35940
import kotlin.reflect.*
@OptIn(ExperimentalAssociatedObjects::class)
@AssociatedObjectKey
@Retention(AnnotationRetention.BINARY)
annotation class Associated(val kClass: KClass<*>)
private interface I1 {
val s: String
}
private class I1Impl : I1 {
override val s = "zzz"
}
private class C(var i1: I1?)
private interface I2 {
fun bar(c: C)
}
private object I2Impl : I2 {
override fun bar(c: C) {
c.i1 = I1Impl()
}
}
@Associated(I2Impl::class)
private class I2ImplHolder
@OptIn(ExperimentalAssociatedObjects::class)
fun testKt35940(): String {
val i2 = I2ImplHolder::class.findAssociatedObject<Associated>()!! as I2
val c = C(null)
i2.bar(c)
return c.i1!!.s
}
@@ -0,0 +1,18 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
private func test1() throws {
try assertEquals(actual: Kt35940Kt.testKt35940(), expected: "zzz")
}
class Kt35940Tests : SimpleTestProvider {
override init() {
super.init()
test("Test1", test1)
}
}
@@ -0,0 +1,36 @@
package kt38641
// See https://youtrack.jetbrains.com/issue/KT-38641.
class KT38641 {
class IntType {
var description = 42
}
class Val {
val description = "val"
}
class Var {
var description = "var"
}
class TwoProperties {
val description = "description"
val description_ = "description_"
}
abstract class OverrideVal {
abstract val description: String
}
interface OverrideVar {
var description: String
}
}
fun getOverrideValDescription(impl: KT38641.OverrideVal) = impl.description
fun getOverrideVarDescription(impl: KT38641.OverrideVar) = impl.description
fun setOverrideVarDescription(impl: KT38641.OverrideVar, newValue: String) {
impl.description = newValue
}
@@ -0,0 +1,74 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
private func testIntType() throws {
let i = KT38641.IntType()
try assertEquals(actual: i.description_, expected: 42)
i.description_ = 17
try assertEquals(actual: i.description_, expected: 17)
}
private func testVal() throws {
try assertEquals(actual: KT38641.Val().description_, expected: "val")
}
private func testVar() throws {
let v = KT38641.Var()
try assertEquals(actual: v.description_, expected: "var")
v.description_ = "newValue"
try assertEquals(actual: v.description_, expected: "newValue")
}
private func testTwoProperties() throws {
let t = KT38641.TwoProperties()
#if !DISABLE_MEMBER_NAME_MANGLING
try assertEquals(actual: t.description_, expected: "description")
try assertEquals(actual: t.description__, expected: "description_")
#endif
}
private func testOverrideVal() throws {
try assertEquals(actual: Kt38641Kt.getOverrideValDescription(impl: KT38641OverrideValImpl()), expected: "description_")
}
class KT38641OverrideValImpl : KT38641.OverrideVal {
override var description_: String {
get {
return "description_"
}
}
}
private func testOverrideVar() throws {
let impl = KT38641OverrideVarImpl()
try assertEquals(actual: Kt38641Kt.getOverrideVarDescription(impl: impl), expected: "description_")
Kt38641Kt.setOverrideVarDescription(impl: impl, newValue: "d")
try assertEquals(actual: Kt38641Kt.getOverrideVarDescription(impl: impl), expected: "d")
}
class KT38641OverrideVarImpl : KT38641OverrideVar {
var description_: String = "description_"
}
class Kt38641Tests : SimpleTestProvider {
override init() {
super.init()
test("TestIntType", testIntType)
test("TestVal", testVal)
test("TestVar", testVar)
test("TestTwoProperties", testTwoProperties)
test("TestOverrideVal", testOverrideVal)
test("TestOverrideVar", testOverrideVar)
}
}
@@ -0,0 +1,17 @@
// See https://youtrack.jetbrains.com/issue/KT-39206.
@Deprecated("Don't call this\nPlease")
fun myFunc() = 17
// See https://youtrack.jetbrains.com/issue/KT-41193.
@Deprecated(
level = DeprecationLevel.ERROR,
message = "This class is deprecated for removal during serialization 1.0 API stabilization.\n" +
"For configuring Json instances, the corresponding builder function can be used instead, e.g. instead of" +
"'Json(JsonConfiguration.Stable.copy(isLenient = true))' 'Json { isLenient = true }' should be used.\n" +
"Instead of storing JsonConfiguration instances of the code, Json instances can be used directly:" +
"'Json(MyJsonConfiguration.copy(prettyPrint = true))' can be replaced with 'Json(from = MyApplicationJson) { prettyPrint = true }'"
)
public open class JsonConfiguration
@Deprecated("'\"\\@\$(){}\r\n")
class MoreTrickyChars
@@ -0,0 +1,18 @@
import Kt
private func test1() throws {
try assertEquals(actual: Kt39206Kt.myFunc(), expected: 17)
}
private func test2() throws {
try assertTrue(MoreTrickyChars() as AnyObject is MoreTrickyChars)
}
class Kt39206Tests : SimpleTestProvider {
override init() {
super.init()
test("Test1", test1)
test("Test2", test2)
}
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package kt41907
class Ckt41907
interface Ikt41907 {
fun foo(c: Ckt41907)
}
private class Bkt41907 {
var c: Ckt41907? = null
}
private val b = Bkt41907()
fun escapeC(c: Ckt41907) {
b.c = c
}
fun testKt41907(o: Ikt41907) {
val c = Ckt41907()
o.foo(c)
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
class Ikt41907Impl : Ikt41907 {
func foo(c: Ckt41907) {
Kt41907Kt.escapeC(c: c)
}
}
private func test1() {
Kt41907Kt.testKt41907(o: Ikt41907Impl())
}
class Kt41907Tests : SimpleTestProvider {
override init() {
super.init()
test("Test1", test1)
}
}
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package kt43599
// Note: this test relies on two-stage compilation.
class KT43599 {
var memberProperty = "memberProperty"
private set
}
var KT43599.extensionProperty
get() = "extensionProperty"
private set(value) { TODO() }
var topLevelProperty
get() = "topLevelProperty"
private set(value) { TODO() }
lateinit var topLevelLateinitProperty: String
private set
fun setTopLevelLateinitProperty(value: String) {
topLevelLateinitProperty = value
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
private func testPropertyWithPrivateSetter() throws {
try assertEquals(actual: KT43599().memberProperty, expected: "memberProperty")
try assertEquals(actual: KT43599().extensionProperty, expected: "extensionProperty")
try assertEquals(actual: Kt43599Kt.topLevelProperty, expected: "topLevelProperty")
// Checking the reported case too:
Kt43599Kt.setTopLevelLateinitProperty(value: "topLevelLateinitProperty")
try assertEquals(actual: Kt43599Kt.topLevelLateinitProperty, expected: "topLevelLateinitProperty")
}
class Kt43599Tests : SimpleTestProvider {
override init() {
super.init()
test("TestPropertyWithPrivateSetter", testPropertyWithPrivateSetter)
}
}
@@ -0,0 +1,62 @@
/*
* Copyright 2010-2021 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.
*/
object KT43780TestObject {
val x = 5
val y = 6
val shared = "shared"
val Shared = "Shared"
}
class KT43780TestClassWithCompanion {
companion object {
val z = 7
}
}
object Shared {
val x = 8
}
class Companion {
val t = 10
companion object {
val x = 9
}
}
enum class KT43780Enum {
OTHER_ENTRY,
COMPANION;
companion object {
val x = 11
}
}
class ClassWithInternalCompanion {
internal companion object {
val x = 12
}
val y = 13
}
class ClassWithPrivateCompanion {
private companion object {
val x = 14
}
val y = 15
}
// Shouldn't be exported at all:
internal class InternalClassWithCompanion {
companion object
}
private class PrivateClassWithCompanion {
companion object
}
@@ -0,0 +1,58 @@
import Kt
private func testObject() throws {
let object = KT43780TestObject.shared
try assertEquals(actual: object.x, expected: 5)
try assertEquals(actual: object.y, expected: 6)
try assertEquals(actual: object.shared, expected: "shared")
try assertEquals(actual: object.Shared, expected: "Shared")
try assertTrue(object === KT43780TestObject())
}
private func testCompanionObject() throws {
let object = KT43780TestClassWithCompanion.companion
try assertEquals(actual: object.z, expected: 7)
try assertTrue(object === KT43780TestClassWithCompanion.Companion())
try assertTrue(object === KT43780TestClassWithCompanion.Companion.shared)
}
private func testNameClash() throws {
let object = Shared.shared
try assertEquals(actual: object.x, expected: 8)
try assertTrue(object === Shared())
let object2 = Companion.companion
try assertEquals(actual: object2.x, expected: 9)
try assertTrue(object2 === Companion.Companion())
let object3 = Companion()
try assertEquals(actual: object3.t, expected: 10)
let object4 = Companion()
try assertEquals(actual: object4.t, expected: 10)
try assertTrue(object3 !== object4)
let object5 = KT43780Enum.Companion()
try assertEquals(actual: object5.x, expected: 11)
try assertTrue(object5 === KT43780Enum.Companion())
let enumEntry : KT43780Enum = KT43780Enum.companion
try assertEquals(actual: enumEntry.name, expected: "COMPANION")
try assertEquals(actual: KT43780Enum.otherEntry.name, expected: "OTHER_ENTRY")
}
// Reported as https://youtrack.jetbrains.com/issue/KT-47462
private func testUnexposedCompanion() throws {
// Just trying to ensure that the classes are accessible:
try assertEquals(actual: 13, expected: ClassWithInternalCompanion().y)
try assertEquals(actual: 15, expected: ClassWithPrivateCompanion().y)
// and this doesn't make the companions accessible as well.
}
class Kt43780Tests : SimpleTestProvider {
override init() {
super.init()
test("testObject", testObject)
test("testCompanionObject", testCompanionObject)
test("testNameClash", testNameClash)
test("testUnexposedCompanion", testUnexposedCompanion)
}
}
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package kt43599
// Based on https://youtrack.jetbrains.com/issue/KT-46431
interface Host {
val test: String
}
abstract class AbstractHost : Host
fun createAbstractHost(): Host {
return object : AbstractHost() {
override val test: String
get() = "1234"
}
}
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
// Based on https://youtrack.jetbrains.com/issue/KT-46431.
private func test1() throws {
try assertEquals(actual: Kt46431Kt.createAbstractHost().test, expected: "1234")
}
class Kt46431Tests : SimpleTestProvider {
override init() {
super.init()
test("Test1", test1)
}
}
@@ -0,0 +1,14 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package kt49937
// Based on https://youtrack.jetbrains.com/issue/KT-49937
final class KT49937 {
override fun toString(): String {
return "KT49937"
}
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
// Based on https://youtrack.jetbrains.com/issue/KT-49937.
public extension KT49937 {
override var description: String { "KT49937Swift" }
}
private func test1() throws {
try assertEquals(actual: KT49937().description, expected: "KT49937Swift")
let nsObject: NSObject = KT49937()
try assertEquals(actual: nsObject.description, expected: "KT49937Swift")
}
class Kt49937Tests : SimpleTestProvider {
override init() {
super.init()
test("Test1", test1)
}
}
@@ -0,0 +1,54 @@
/*
* 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.
*/
@file:MyCustomFileAspect(type = "kt")
@Target(AnnotationTarget.FILE)
annotation class MyCustomFileAspect(val type: String = "kt")
annotation class NoDoc
@MustBeDocumented
annotation class Foo
@MustBeDocumented
annotation class BugReport(
val assignedTo: String = "[none]",
val status: String = "open"
)
@NoDoc
@Foo
@BugReport(assignedTo = "me", status = "open")
interface MyInterface {
}
@NoDoc
@Foo
@BugReport(assignedTo = "me", status = "open")
class Bar {
@NoDoc
@Foo
@Deprecated("warning", level = DeprecationLevel.WARNING)
/**
* My method
* @param nodocParam is one arg
* @param fooParam is second arg
* @return their sum
*/
protected suspend fun baz (@NoDoc nodocParam:Int, @Foo @BugReport(assignedTo = "me", status = "fixed") fooParam:Int): Int { return nodocParam + fooParam }
/** My property
***
*
*/
@Foo
@BugReport(assignedTo = "me", status = "open")
val greeting: String
get() {
return "Hello World!"
}
// Not a kDoc-formatted comment
protected val farewell: String
get() { return "Bye bye!" }
}
@@ -0,0 +1,24 @@
/*
* 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 kt54119
class KT54119KotlinKey
private typealias Foo = KT54119KotlinKey
fun callContains(set: Set<*>) = set.contains(Foo())
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
fun callGetElement(set: Set<*>) = (set as kotlin.native.internal.KonanSet<Any?>).getElement(Foo())
fun callContainsKey(map: Map<*, *>) = map.containsKey(Foo())
fun callContainsValue(map: Map<*, *>) = map.containsValue(Foo())
fun callGet(map: Map<*, *>) = map.get(Foo())
fun callGetOrThrowConcurrentModification(map: Map<*, *>) = map.hashCode() // calls getOrThrowConcurrentModification under the hood.
fun callContainsEntry(map: Map<*, *>) = map.entries.contains(map.entries.first())
@@ -0,0 +1,51 @@
/*
* 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.
*/
import Foundation
import Kt
// See https://youtrack.jetbrains.com/issue/KT-54119/Native-runtime-assertion-failed-due-to-missing-thread-state-switch
private func testSetContains() throws {
try assertFalse(Kt54119Kt.callContains(set: ["111"]))
}
private func testSetGetElement() throws {
try assertNil(Kt54119Kt.callGetElement(set: [222]))
}
private func testMapContainsKey() throws {
try assertFalse(Kt54119Kt.callContainsKey(map: ["abc" : "def"]))
}
private func testMapContainsValue() throws {
try assertFalse(Kt54119Kt.callContainsValue(map: [KT54119KotlinKey() : 1]))
}
private func testMapGet() throws {
try assertNil(Kt54119Kt.callGet(map: [0 : 0]))
}
private func testMapGetOrThrowConcurrentModification() throws {
Kt54119Kt.callGetOrThrowConcurrentModification(map: [KT54119KotlinKey() : 2])
}
private func testMapContainsEntry() throws {
try assertTrue(Kt54119Kt.callContainsEntry(map: [KT54119KotlinKey() : 3]))
}
class Kt54119Tests : SimpleTestProvider {
override init() {
super.init()
test("testSetContains", testSetContains)
test("testSetGetElement", testSetGetElement)
test("testMapContainsKey", testMapContainsKey)
test("testMapContainsValue", testMapContainsValue)
test("testMapGet", testMapGet)
test("testMapGetOrThrowConcurrentModification", testMapGetOrThrowConcurrentModification)
test("testMapContainsEntry", testMapContainsEntry)
}
}
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2023 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.
*/
import kotlin.sequences.*
suspend fun SequenceScope<Int>.fill() {
yield(1)
yield(2)
}
fun getFillFunction() = SequenceScope<Int>::fill
fun callback(block: suspend SequenceScope<Int>.() -> Unit) : List<Int> {
return sequence {
block()
}.toList()
}
@@ -0,0 +1,22 @@
/*
* 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.
*/
import Foundation
import Kt
private func testFill() throws {
let result = Kt55736Kt.callback(block: Kt55736Kt.getFillFunction())
try assertEquals(actual: result.count, expected: 2)
try assertEquals(actual: result[0], expected: 1)
try assertEquals(actual: result[1], expected: 2)
}
class Kt55736Tests : SimpleTestProvider {
override init() {
super.init()
test("testFill", testFill)
}
}
@@ -0,0 +1,17 @@
/*
* Copyright 2010-2023 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.
*/
var initialized = 0
object Kt56521 {
init {
initialized = 1
}
}
fun getKt56521(): Kt56521 {
Kt56521
return Kt56521
}
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2023 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.
*/
import Kt
func testKt56521() throws {
let object = Kt56521()
try assertTrue(object is Kt56521)
try assertEquals(actual: Kt56521Kt.initialized, expected: 1)
}
class Kt56521Tests : SimpleTestProvider {
override init() {
super.init()
test("testKt56521", testKt56521)
}
}
@@ -0,0 +1,14 @@
/*
* Copyright 2010-2023 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.
*/
interface IKt57373 {
val bar: Int
}
class DKt57373(foo: IKt57373) : IKt57373 by foo
class CKt57373 : IKt57373 {
override val bar: Int = 42
}
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2023 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.
*/
import Kt
func testKt57373() throws {
let impl = CKt57373()
let x = DKt57373(foo: impl)
try assertEquals(actual: x.bar, expected: 42)
}
class Kt57373Tests : SimpleTestProvider {
override init() {
super.init()
test("testKt57373", testKt57373)
}
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2023 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 kt57791
abstract class Ckt57791 {
abstract fun baz(): Int
}
object Okt57791 : Ckt57791() {
override fun baz() = 117
}
class Ckt57791Final : Ckt57791() {
override fun baz() = 42
}
interface Foo {
fun getCkt57791(): Ckt57791Final
}
fun foobar(f: Boolean, foo: Foo): Boolean {
val z = if (f) Okt57791 else foo.getCkt57791()
return z.baz() == 42
}
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2023 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.
*/
import Kt
class FooImpl : Foo {
func getCkt57791() -> Ckt57791Final { return Ckt57791Final() }
}
func testKt57791() throws {
try assertTrue(Kt57791Kt.foobar(f: false, foo: FooImpl()))
}
class Kt57791Tests : SimpleTestProvider {
override init() {
super.init()
test("testKt57791", testKt57791)
}
}
@@ -0,0 +1,18 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package library
fun readDataFromLibraryClass(input: A): String {
return input.data
}
fun readDataFromLibraryInterface(input: I): String {
return input.data
}
fun readDataFromLibraryEnum(input: E): String {
return input.data
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
func testAccessClassFromLibraryWithShortName() throws {
let object: MyLibraryA = MyLibraryA(data: "Data from Class")
let interface: MyLibraryI = MyLibraryA(data: "Data from Interface")
let enumObject: MyLibraryE = MyLibraryE.b
let dataFromClass = LibraryKt.readDataFromLibraryClass(input: object)
let dataFromInterface = LibraryKt.readDataFromLibraryInterface(input: interface)
let dataFromEnum = LibraryKt.readDataFromLibraryEnum(input: enumObject)
try assertEquals(actual: dataFromClass, expected: "Data from Class")
try assertEquals(actual: dataFromInterface, expected: "Data from Interface")
try assertEquals(actual: dataFromEnum, expected: "Enum entry B")
}
class LibraryTests : SimpleTestProvider {
override init() {
super.init()
test("testAccessClassFromLibraryWithShortName", testAccessClassFromLibraryWithShortName)
}
}
@@ -0,0 +1,18 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
package library
interface I {
val data: String
}
class A(override val data: String): I
enum class E(val data: String) {
A("Enum entry A"),
B("Enum entry B"),
C("Enum entry C")
}
@@ -0,0 +1,48 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
// All classes and methods should be used in tests
@file:Suppress("UNUSED")
package localEA
class ArraysConstructor {
private val memberArray: IntArray
constructor(int1: Int, int2: Int) {
memberArray = IntArray(2)
set(int1, int2)
}
fun set(int1: Int, int2: Int) {
memberArray[0] = int1
memberArray[1] = int2
}
fun log() = "size: ${memberArray.size}, contents: ${memberArray.contentToString()}"
}
class ArraysDefault {
private val memberArray = IntArray(2)
constructor(int1: Int, int2: Int) {
set(int1, int2)
}
fun set(int1: Int, int2: Int) {
memberArray[0] = int1
memberArray[1] = int2
}
fun log() = "size: ${memberArray.size}, contents: ${memberArray.contentToString()}"
}
class ArraysInitBlock {
private val memberArray : IntArray
init {
memberArray = IntArray(2)
}
constructor(int1: Int, int2: Int) {
set(int1, int2)
}
fun set(int1: Int, int2: Int) {
memberArray[0] = int1
memberArray[1] = int2
}
fun log() = "size: ${memberArray.size}, contents: ${memberArray.contentToString()}"
}
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
// -------- Tests --------
func testArraysEscapeAsParameter() throws {
let array1 = ArraysConstructor(int1: 1, int2: 2)
try assertEquals(actual: array1.log(), expected: "size: 2, contents: [1, 2]", "Wrong array values in class ArraysConstructor.")
array1.set(int1: 3, int2: 4)
try assertEquals(actual: array1.log(), expected: "size: 2, contents: [3, 4]", "Wrong array values in class ArraysConstructor.")
let array2 = ArraysDefault(int1: 1, int2: 2)
try assertEquals(actual: array2.log(), expected: "size: 2, contents: [1, 2]", "Wrong array values in class ArraysDefault.")
array2.set(int1: 3, int2: 4)
try assertEquals(actual: array2.log(), expected: "size: 2, contents: [3, 4]", "Wrong array values in class ArraysDefault.")
let array3 = ArraysInitBlock(int1: 1, int2: 2)
try assertEquals(actual: array3.log(), expected: "size: 2, contents: [1, 2]", "Wrong array values in class ArraysInitBlock.")
array3.set(int1: 3, int2: 4)
try assertEquals(actual: array3.log(), expected: "size: 2, contents: [3, 4]", "Wrong array values in class ArraysInitBlock.")
}
// -------- Execution of the test --------
class LocalEATests : SimpleTestProvider {
override init() {
super.init()
test("TestArraysEscapeAsParameter", testArraysEscapeAsParameter)
}
}
@@ -0,0 +1,205 @@
package noAutorelease
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
import kotlin.native.internal.NativePtr
import kotlin.native.ref.WeakReference
import kotlin.test.*
@OptIn(kotlin.experimental.ExperimentalNativeApi::class)
class KotlinLivenessTracker {
val weakRefs = mutableListOf<WeakReference<Any>>()
fun add(obj: Any?) {
assertNotNull(obj)
weakRefs += WeakReference(obj)
assertFalse(objectsAreDead())
}
fun isEmpty() = weakRefs.isEmpty()
fun objectsAreDead() = weakRefs.all { it.value === null }
}
@OptIn(kotlin.native.runtime.NativeRuntimeApi::class)
fun gc() = kotlin.native.runtime.GC.collect()
class KotlinObject
interface NoAutoreleaseSendHelper {
fun sendKotlinObject(kotlinObject: KotlinObject)
fun blockReceivingKotlinObject(): (KotlinObject) -> Unit
fun sendSwiftObject(swiftObject: Any)
fun sendList(list: List<*>)
fun sendString(string: String)
fun sendNumber(number: Any)
fun sendBlock(block: () -> KotlinObject)
suspend fun sendCompletion(): Any?
}
interface NoAutoreleaseReceiveHelper {
fun receiveKotlinObject(): KotlinObject
fun receiveSwiftObject(): Any
fun receiveList(): List<*>
fun receiveString(): String
fun receiveNumber(): Any
fun receiveBlock(): () -> KotlinObject
}
class NoAutoreleaseKotlinSendHelper(val kotlinLivenessTracker: KotlinLivenessTracker) : NoAutoreleaseSendHelper {
override fun sendKotlinObject(kotlinObject: KotlinObject) = kotlinLivenessTracker.add(kotlinObject)
override fun blockReceivingKotlinObject(): (KotlinObject) -> Unit = { kotlinLivenessTracker.add(it) }
override fun sendSwiftObject(swiftObject: Any) = kotlinLivenessTracker.add(swiftObject)
override fun sendList(list: List<*>) = kotlinLivenessTracker.add(list)
override fun sendString(string: String) = kotlinLivenessTracker.add(string)
override fun sendNumber(number: Any) = kotlinLivenessTracker.add(number)
override fun sendBlock(block: () -> KotlinObject) = kotlinLivenessTracker.add(block)
override suspend fun sendCompletion() = suspendCoroutineUninterceptedOrReturn<Any?> { continuation ->
kotlinLivenessTracker.add(continuation)
null
}
}
class NoAutoreleaseKotlinReceiveHelper(val kotlinLivenessTracker: KotlinLivenessTracker) : NoAutoreleaseReceiveHelper {
private val kotlinObject = KotlinObject()
lateinit var swiftObject: Any
private val list = listOf(Any())
private val string = Any().toString()
private val number = createKotlinNumber()
private val block = createLambda(kotlinLivenessTracker)
override fun receiveKotlinObject(): KotlinObject = kotlinObject.also { kotlinLivenessTracker.add(it) }
override fun receiveSwiftObject(): Any = swiftObject.also { kotlinLivenessTracker.add(it) }
override fun receiveList(): List<*> = list.also { kotlinLivenessTracker.add(it) }
override fun receiveString(): String = string.also { kotlinLivenessTracker.add(it) }
override fun receiveNumber(): Any = number.also { kotlinLivenessTracker.add(it) }
override fun receiveBlock(): () -> KotlinObject = block.also { kotlinLivenessTracker.add(it) }
}
object NoAutoreleaseSingleton {
val x = 1
}
enum class NoAutoreleaseEnum {
ENTRY;
val x = 2
}
fun callSendKotlinObject(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
val kotlinObject = KotlinObject()
// Repeating twice to cover possible fast paths after caching something for an object.
helper.sendKotlinObject(kotlinObject)
helper.sendKotlinObject(kotlinObject)
tracker.add(kotlinObject)
}
fun sendKotlinObjectToBlock(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
val kotlinObject = KotlinObject()
helper.blockReceivingKotlinObject()(kotlinObject)
helper.blockReceivingKotlinObject()(kotlinObject)
tracker.add(kotlinObject)
}
fun callSendSwiftObject(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker, swiftObject: Any) {
helper.sendSwiftObject(swiftObject)
helper.sendSwiftObject(swiftObject)
tracker.add(swiftObject)
}
fun callSendList(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
val list = listOf(Any())
helper.sendList(list)
helper.sendList(list)
tracker.add(list)
}
fun callSendString(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
val string = Any().toString()
helper.sendString(string)
helper.sendString(string)
tracker.add(string)
}
fun callSendNumber(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
val number = createKotlinNumber()
helper.sendNumber(number)
helper.sendNumber(number)
tracker.add(number)
}
fun callSendBlock(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
val block = createLambda()
helper.sendBlock(block)
helper.sendBlock(block)
tracker.add(block)
}
private class EmptyContinuation : Continuation<Any?> {
override val context: CoroutineContext = EmptyCoroutineContext
override fun resumeWith(result: Result<Any?>) { result.getOrThrow() }
}
fun callSendCompletion(helper: NoAutoreleaseSendHelper, tracker: KotlinLivenessTracker) {
val completion = EmptyContinuation()
suspend {
helper.sendCompletion()
helper.sendCompletion()
}.startCoroutine(completion)
tracker.add(completion)
}
fun callReceiveKotlinObject(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
tracker.add(helper.receiveKotlinObject())
}
fun callReceiveSwiftObject(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
tracker.add(helper.receiveSwiftObject())
}
fun callReceiveList(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
tracker.add(helper.receiveList())
}
fun callReceiveString(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
tracker.add(helper.receiveString())
}
fun callReceiveNumber(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
tracker.add(helper.receiveNumber())
}
fun callReceiveBlock(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
tracker.add(helper.receiveBlock())
}
fun callReceiveBlockAndCall(helper: NoAutoreleaseReceiveHelper, tracker: KotlinLivenessTracker) = repeat(2) {
tracker.add(helper.receiveBlock()())
}
fun objc_autoreleasePoolPush() = kotlinx.cinterop.objc_autoreleasePoolPush()
fun objc_autoreleasePoolPop(handle: NativePtr) = kotlinx.cinterop.objc_autoreleasePoolPop(handle)
fun useIntArray(array: IntArray) {} // Just to make IntArray available from Swift.
private fun createLambda(): () -> KotlinObject {
val lambdaResult = KotlinObject()
return { lambdaResult } // make it capturing thus dynamic.
}
private fun createLambda(kotlinLivenessTracker: KotlinLivenessTracker): () -> KotlinObject {
val lambdaResult = KotlinObject()
return {
val result = lambdaResult // make it capturing thus dynamic.
kotlinLivenessTracker.add(result)
result
}
}
private fun createKotlinNumber(): Any = (0.5 + Any().hashCode().toDouble()) // to make it dynamic.
@@ -0,0 +1,514 @@
import Kt
private class SwiftLivenessTracker {
class SwiftWeakRef {
weak var value: AnyObject?
}
var weakRefs: [SwiftWeakRef] = []
func add(_ obj: AnyObject?) {
try! assertTrue(obj != nil)
let weakRef = SwiftWeakRef()
weakRef.value = obj
weakRefs.append(weakRef)
try! assertFalse(objectsAreDead())
}
func isEmpty() -> Bool {
return weakRefs.isEmpty
}
func objectsAreDead() -> Bool {
for weakRef in weakRefs {
if weakRef.value !== nil { return false }
}
return true
}
}
private class NoAutoreleaseSwiftHelper : NoAutoreleaseSendHelper, NoAutoreleaseReceiveHelper {
fileprivate var swiftLivenessTracker: SwiftLivenessTracker
init(swiftLivenessTracker: SwiftLivenessTracker) {
self.swiftLivenessTracker = swiftLivenessTracker
}
func sendKotlinObject(kotlinObject: KotlinObject) {
swiftLivenessTracker.add(kotlinObject)
}
func blockReceivingKotlinObject() -> (KotlinObject) -> Void {
return {
self.swiftLivenessTracker.add($0)
}
}
func sendSwiftObject(swiftObject: Any) {
swiftLivenessTracker.add(swiftObject as AnyObject)
}
func sendList(list: [Any]) {
}
func sendString(string: String) {
}
func sendNumber(number: Any) {
swiftLivenessTracker.add(number as AnyObject)
}
func sendBlock(block: @escaping () -> KotlinObject) {
}
func sendCompletion(completionHandler: @escaping (Any?, Error?) -> Void) {
completionHandler(nil, nil)
}
let kotlinObject = KotlinObject()
let swiftObject = SwiftObject2()
let list = createList()
let string = createString()
let number = createNumber()
lazy var block = createBlock(swiftLivenessTracker: swiftLivenessTracker)
func receiveKotlinObject() -> KotlinObject {
let result = kotlinObject
swiftLivenessTracker.add(result)
return result
}
func receiveSwiftObject() -> Any {
let result = swiftObject
swiftLivenessTracker.add(result)
return result
}
func receiveList() -> [Any] {
return list
}
func receiveString() -> String {
return string
}
func receiveNumber() -> Any {
let result = number
swiftLivenessTracker.add(result)
return number
}
func receiveBlock() -> (() -> KotlinObject) {
return block
}
}
private struct TestFlags {
var trackSwiftLifetime: Bool = true
var checkAutorelease: Bool = true
// When Kotlin refers to a Swift object which refers to a Kotlin object, to reclaim the latter
// we have to run the GC twice if experimental MM is enabled:
// first GC finds the Kotlin wrapper of the Swift object and releases it during the sweep phase.
// The second GC is then able to reclaim the Kotlin object.
// This behaviour is different from the legacy MM, which calls objc_release right in the middle of the GC,
// so is able to process its outcome during the same GC.
var runGCTwice: Bool = false
}
private func testOnce(flags: TestFlags, block: (KotlinLivenessTracker, SwiftLivenessTracker) throws -> Void) throws {
try assertAutoreleasepoolNotUsed(flags: flags) { // Note: this assertion will also fail if something in the "test infra" below uses autoreleasepool.
let kotlinLivenessTracker = KotlinLivenessTracker()
let swiftLivenessTracker = SwiftLivenessTracker()
try assertTrue(kotlinLivenessTracker.isEmpty())
try assertTrue(swiftLivenessTracker.isEmpty())
try block(kotlinLivenessTracker, swiftLivenessTracker)
NoAutoreleaseKt.gc()
if (flags.runGCTwice) {
NoAutoreleaseKt.gc()
}
try assertFalse(kotlinLivenessTracker.isEmpty())
if flags.trackSwiftLifetime {
try assertFalse(swiftLivenessTracker.isEmpty())
} else {
// Note: some of the tests don't actually add objects to the swiftLivenessTracker,
// because e.g. Swift represents certain Obj-C classes as value types.
try assertTrue(swiftLivenessTracker.isEmpty())
}
#if !NOOP_GC
// If something has "leaked" to autoreleasepool, one of the assertions below should fail:
try assertTrue(kotlinLivenessTracker.objectsAreDead())
try assertTrue(swiftLivenessTracker.objectsAreDead())
#endif
}
}
private func test(flags: TestFlags, block: (KotlinLivenessTracker, SwiftLivenessTracker) -> Void) throws {
for _ in 1...2 {
// Repeating twice to cover possible fast paths after caching something for a type.
try testOnce(flags: flags, block: block)
}
}
private func assertAutoreleasepoolNotUsed(flags: TestFlags = TestFlags(), block: () throws -> Void) throws {
let poolBefore = NoAutoreleaseKt.objc_autoreleasePoolPush()
NoAutoreleaseKt.objc_autoreleasePoolPop(handle: poolBefore)
try block()
let poolAfter = NoAutoreleaseKt.objc_autoreleasePoolPush()
NoAutoreleaseKt.objc_autoreleasePoolPop(handle: poolAfter)
// autoreleasepool machinery is implemented as a stack.
// So here we check that stack top after `block()` is the same as before.
// Which means that no objects were added to this stack inbetween.
if flags.checkAutorelease {
try assertEquals(actual: poolAfter, expected: poolBefore)
} else {
// Just to ensure we disable the hack once it is not needed anymore:
try assertFalse(poolAfter == poolBefore)
}
}
private func testSendToKotlin<T>(
_ createObject: () -> T,
flags: TestFlags = TestFlags(),
sendObject: (NoAutoreleaseKotlinSendHelper, T) -> Void
) throws {
try test(flags: flags) { kotlinLivenessTracker, swiftLivenessTracker in
let helper = NoAutoreleaseKotlinSendHelper(kotlinLivenessTracker: kotlinLivenessTracker)
let obj = createObject()
if flags.trackSwiftLifetime {
swiftLivenessTracker.add(obj as AnyObject)
}
// Repeating twice to cover possible fast paths after caching something for an object.
sendObject(helper, obj)
sendObject(helper, obj)
}
}
private func testReceiveFromKotlin<T>(flags: TestFlags = TestFlags(), receiveObject: (NoAutoreleaseKotlinReceiveHelper) -> T) throws {
try test(flags: flags) { kotlinLivenessTracker, swiftLivenessTracker in
let helper = NoAutoreleaseKotlinReceiveHelper(kotlinLivenessTracker: kotlinLivenessTracker)
// Repeating twice to cover possible fast paths after caching something for an object.
let obj1 = receiveObject(helper)
let obj2 = receiveObject(helper)
if flags.trackSwiftLifetime {
swiftLivenessTracker.add(obj1 as AnyObject)
swiftLivenessTracker.add(obj2 as AnyObject)
}
}
}
private func testCallToSwift(flags: TestFlags = TestFlags(), callKotlin: (NoAutoreleaseSwiftHelper, KotlinLivenessTracker) -> Void) throws {
try test(flags: flags) { kotlinLivenessTracker, swiftLivenessTracker in
let helper = NoAutoreleaseSwiftHelper(swiftLivenessTracker: swiftLivenessTracker)
callKotlin(helper, kotlinLivenessTracker)
}
}
private class SwiftObject1 {}
private class SwiftObject2 {}
private class SwiftObject3 {}
private class SwiftObject4 {}
private func testSendKotlinObjectToKotlin() throws {
try testSendToKotlin({ KotlinObject() }) {
$0.sendKotlinObject(kotlinObject: $1)
}
}
private func testSendKotlinObjectToKotlinBlock() throws {
try testSendToKotlin({ KotlinObject() }) {
$0.blockReceivingKotlinObject()($1)
}
}
private func testSendSwiftObjectToKotlin() throws {
try testSendToKotlin({ SwiftObject1() }) {
$0.sendSwiftObject(swiftObject: $1)
}
}
private func testSendListToKotlin() throws {
try testSendToKotlin({ createList() }, flags: TestFlags(trackSwiftLifetime: false)) {
$0.sendList(list: $1)
}
}
private func testSendStringToKotlin() throws {
try testSendToKotlin({ createString() }, flags: TestFlags(trackSwiftLifetime: false)) {
$0.sendString(string: $1)
}
}
private func testSendNumberToKotlin() throws {
try testSendToKotlin({ createNumber() }) {
$0.sendNumber(number: $1)
}
}
private func testSendBlockToKotlin() throws {
try testSendToKotlin({ createBlock() }, flags: TestFlags(trackSwiftLifetime: false)) {
$0.sendBlock(block: $1)
}
}
private func testSendCompletionToKotlin() throws {
try testSendToKotlin({ createCompletion() }, flags: TestFlags(trackSwiftLifetime: false)) {
$0.sendCompletion(completionHandler: $1)
}
}
private func testReceiveKotlinObjectFromKotlin() throws {
try testReceiveFromKotlin {
$0.receiveKotlinObject()
}
}
private func testReceiveSwiftObjectFromKotlin() throws {
try testReceiveFromKotlin { (helper: NoAutoreleaseKotlinReceiveHelper) -> Any in
helper.swiftObject = SwiftObject3()
return helper.receiveSwiftObject()
}
}
private func testReceiveListFromKotlin() throws {
// Swift conversion from NSArray to Swift Array uses non-optimized autorelease in the implementation,
// So regardless of our efforts, passing List from Kotlin to Swift will use autoreleasepool.
// Use `checkAutorelease: false` flag to disable the relevant check.
try testReceiveFromKotlin(flags: TestFlags(trackSwiftLifetime: false, checkAutorelease: false)) {
$0.receiveList()
}
}
private func testReceiveStringFromKotlin() throws {
try testReceiveFromKotlin(flags: TestFlags(trackSwiftLifetime: false)) {
$0.receiveString()
}
}
private func testReceiveNumberFromKotlin() throws {
try testReceiveFromKotlin {
$0.receiveNumber()
}
}
private func testReceiveBlockFromKotlin() throws {
try testReceiveFromKotlin(flags: TestFlags(trackSwiftLifetime: false)) {
$0.receiveBlock()
}
}
private func testReceiveBlockFromKotlinAndCall() throws {
try testReceiveFromKotlin {
$0.receiveBlock()()
}
}
private func testCreateKotlinArray() throws {
try testReceiveFromKotlin { (helper: NoAutoreleaseKotlinReceiveHelper) -> KotlinIntArray in
let array = KotlinIntArray(size: 2)
helper.kotlinLivenessTracker.add(obj: array)
return array
}
}
private func testGetKotlinUnit() throws {
try assertAutoreleasepoolNotUsed {
try assertSame(actual: KotlinUnit.shared, expected: KotlinUnit.shared)
}
}
private func testGetKotlinSingleton() throws {
try assertAutoreleasepoolNotUsed {
try assertEquals(actual: NoAutoreleaseSingleton.shared.x, expected: 1)
}
}
private func testGetKotlinEnumEntry() throws {
try assertAutoreleasepoolNotUsed {
try assertEquals(actual: NoAutoreleaseEnum.entry.x, expected: 2)
}
}
private func testSendKotlinObjectToSwift() throws {
try testCallToSwift {
NoAutoreleaseKt.callSendKotlinObject(helper: $0, tracker: $1)
}
}
private func testSendKotlinObjectToSwiftBlock() throws {
try testCallToSwift {
NoAutoreleaseKt.sendKotlinObjectToBlock(helper: $0, tracker: $1)
}
}
private func testSendSwiftObjectToSwift() throws {
try testCallToSwift {
NoAutoreleaseKt.callSendSwiftObject(helper: $0, tracker: $1, swiftObject: SwiftObject4())
}
}
private func testSendListToSwift() throws {
// Swift conversion from NSArray to Swift Array uses non-optimized autorelease in the implementation,
// So regardless of our efforts, passing List from Kotlin to Swift will use autoreleasepool.
// Use `checkAutorelease: false` flag to disable the relevant check.
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false, checkAutorelease: false)) {
NoAutoreleaseKt.callSendList(helper: $0, tracker: $1)
}
}
private func testSendStringToSwift() throws {
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false)) {
NoAutoreleaseKt.callSendString(helper: $0, tracker: $1)
}
}
private func testSendNumberToSwift() throws {
try testCallToSwift {
NoAutoreleaseKt.callSendNumber(helper: $0, tracker: $1)
}
}
private func testSendBlockToSwift() throws {
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false)) {
NoAutoreleaseKt.callSendBlock(helper: $0, tracker: $1)
}
}
private func testSendCompletionToSwift() throws {
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false)) {
NoAutoreleaseKt.callSendCompletion(helper: $0, tracker: $1)
}
}
private func testReceiveKotlinObjectFromSwift() throws {
try testCallToSwift(flags: TestFlags(runGCTwice: true)) {
NoAutoreleaseKt.callReceiveKotlinObject(helper: $0, tracker: $1)
}
}
private func testReceiveSwiftObjectFromSwift() throws {
try testCallToSwift {
NoAutoreleaseKt.callReceiveSwiftObject(helper: $0, tracker: $1)
}
}
private func testReceiveListFromSwift() throws {
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false)) {
NoAutoreleaseKt.callReceiveList(helper: $0, tracker: $1)
}
}
private func testReceiveStringFromSwift() throws {
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false)) {
NoAutoreleaseKt.callReceiveString(helper: $0, tracker: $1)
}
}
private func testReceiveNumberFromSwift() throws {
try testCallToSwift {
NoAutoreleaseKt.callReceiveNumber(helper: $0, tracker: $1)
}
}
private func testReceiveBlockFromSwift() throws {
try testCallToSwift(flags: TestFlags(trackSwiftLifetime: false)) {
NoAutoreleaseKt.callReceiveBlock(helper: $0, tracker: $1)
}
}
private func testReceiveBlockFromSwiftAndCall() throws {
try testCallToSwift(flags: TestFlags(runGCTwice: true)) {
NoAutoreleaseKt.callReceiveBlockAndCall(helper: $0, tracker: $1)
}
}
private func createList() -> [Any] {
return [NSObject()]
}
private func createBlock() -> () -> KotlinObject {
let blockResult = KotlinObject()
return { return blockResult } // Make capturing thus dynamic.
}
private func createBlock(swiftLivenessTracker: SwiftLivenessTracker) -> () -> KotlinObject {
let blockResult = KotlinObject()
return {
let result = blockResult // Make capturing thus dynamic.
swiftLivenessTracker.add(result)
return result
}
}
private func createCompletion() -> (Any?, Error?) -> Void {
return { _, _ in }
}
private func createString() -> String {
return NSObject().description // Make it dynamic.
}
private func createNumber() -> NSNumber {
return (0.5 + Double(NSObject().hash)) as NSNumber
}
class NoAutoreleaseTests : SimpleTestProvider {
override init() {
super.init()
test("testSendKotlinObjectToKotlin", testSendKotlinObjectToKotlin)
test("testSendKotlinObjectToKotlinBlock", testSendKotlinObjectToKotlinBlock)
test("testSendSwiftObjectToKotlin", testSendSwiftObjectToKotlin)
test("testSendListToKotlin", testSendListToKotlin)
test("testSendStringToKotlin", testSendStringToKotlin)
test("testSendNumberToKotlin", testSendNumberToKotlin)
test("testSendBlockToKotlin", testSendBlockToKotlin)
test("testSendCompletionToKotlin", testSendCompletionToKotlin)
test("testReceiveKotlinObjectFromKotlin", testReceiveKotlinObjectFromKotlin)
test("testReceiveSwiftObjectFromKotlin", testReceiveSwiftObjectFromKotlin)
test("testReceiveListFromKotlin", testReceiveListFromKotlin)
test("testReceiveStringFromKotlin", testReceiveStringFromKotlin)
test("testReceiveNumberFromKotlin", testReceiveNumberFromKotlin)
test("testReceiveBlockFromKotlin", testReceiveBlockFromKotlin)
test("testReceiveBlockFromKotlinAndCall", testReceiveBlockFromKotlinAndCall)
test("testCreateKotlinArray", testCreateKotlinArray)
test("testGetKotlinUnit", testGetKotlinUnit)
test("testGetKotlinSingleton", testGetKotlinSingleton)
test("testGetKotlinEnumEntry", testGetKotlinEnumEntry)
test("testSendKotlinObjectToSwift", testSendKotlinObjectToSwift)
test("testSendKotlinObjectToSwiftBlock", testSendKotlinObjectToSwiftBlock)
test("testSendSwiftObjectToSwift", testSendSwiftObjectToSwift)
test("testSendListToSwift", testSendListToSwift)
test("testSendStringToSwift", testSendStringToSwift)
test("testSendNumberToSwift", testSendNumberToSwift)
test("testSendBlockToSwift", testSendBlockToSwift)
test("testSendCompletionToSwift", testSendCompletionToSwift)
test("testReceiveKotlinObjectFromSwift", testReceiveKotlinObjectFromSwift)
test("testReceiveSwiftObjectFromSwift", testReceiveSwiftObjectFromSwift)
test("testReceiveListFromSwift", testReceiveListFromSwift)
test("testReceiveStringFromSwift", testReceiveStringFromSwift)
test("testReceiveNumberFromSwift", testReceiveNumberFromSwift)
test("testReceiveBlockFromSwift", testReceiveBlockFromSwift)
test("testReceiveBlockFromSwiftAndCall", testReceiveBlockFromSwiftAndCall)
}
}
@@ -0,0 +1,12 @@
/*
* Copyright 2010-2023 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 noEnumEntries
enum class NoEnumEntriesEnum {
ONE,
TWO,
THREE
}
@@ -0,0 +1,84 @@
import Kt
private func testObjCNameClassNames() throws {
try assertEquals(actual: ObjCNameC1A().foo(), expected: "a")
try assertEquals(actual: ObjCNameC1B().foo(), expected: "b")
}
private func testObjCNameFunctionName() throws {
try assertEquals(actual: ObjCNameAKt.with(userId: "abc"), expected: "abc")
}
private func testObjCNameParameterNames() throws {
try assertEquals(actual: ObjCNameAKt.supports(true), expected: true)
try assertEquals(actual: ObjCNameAKt.scanForPeripherals(withServices: 123, options: "abc"), expected: "123 abc")
try assertEquals(actual: ObjCNameAKt.registerForConnectionEvents(options: "abc"), expected: "abc")
}
private func testObjCNameReceiverName() throws {
let object = SwiftNameC2()
try assertEquals(actual: ObjCNameBKt.getSomeValue(of: object), expected: 0)
}
private func testObjCNameMySwiftArray() throws {
let array = MySwiftArray()
try assertEquals(actual: array.count, expected: 0)
try assertEquals(actual: array.index(of: 1), expected: 1)
}
private func testObjCNameOverrides() throws {
let object = SwiftNameC2()
try assertEquals(actual: object.someOtherValue, expected: 0)
object.someOtherValue = 1
try assertEquals(actual: object.someOtherValue, expected: 1)
try assertEquals(actual: object.someOtherFunction(receiver: 2, otherParam: 4), expected: 8)
try assertEquals(actual: ObjCNameC4().foo(objCReceiver: 3, objCParam: 5), expected: 15)
}
private func testObjCNameNestedClass() throws {
let object = SwiftNameC2.SwiftNestedClass()
try assertEquals(actual: object.nestedValue, expected: 1)
object.nestedValue = 2
try assertEquals(actual: object.nestedValue, expected: 2)
}
private func testObjCNameExact() throws {
try assertEquals(actual: SwiftExactNestedClass().nestedValue, expected: 1)
try assertEquals(actual: SwiftNameC3.SwiftNestedClass().nestedValue, expected: 2)
}
private func testObjCNameObject() throws {
try assertEquals(actual: ObjCNameSwiftObject.shared, expected: ObjCNameSwiftObject())
}
private func testObjCNameEnum() throws {
let enumValues = ObjCNameSwiftEnum.values()
try assertEquals(actual: enumValues.size, expected: 3)
try assertSame(actual: enumValues.get(index: 0) as AnyObject, expected: ObjCNameSwiftEnum.swiftOne)
try assertSame(actual: enumValues.get(index: 1) as AnyObject, expected: ObjCNameSwiftEnum.companion)
try assertSame(actual: enumValues.get(index: 2) as AnyObject, expected: ObjCNameSwiftEnum.swiftThree)
try assertEquals(actual: ObjCNameSwiftEnum.Companion.shared.foo(), expected: 0)
}
private func testObjCAvoidPreprocessorName() throws {
let instance = ObjCAvoidPreprocessorName(time: 42)
try assertEquals(actual: instance.time, expected: 42)
}
class ObjCNameTests : SimpleTestProvider {
override init() {
super.init()
test("TestObjCNameClassNames", testObjCNameClassNames)
test("TestObjCNameFunctionName", testObjCNameFunctionName)
test("TestObjCNameParameterNames", testObjCNameParameterNames)
test("TestObjCNameReceiverName", testObjCNameReceiverName)
test("TestObjCNameMySwiftArray", testObjCNameMySwiftArray)
test("TestObjCNameOverrides", testObjCNameOverrides)
test("TestObjCNameNestedClass", testObjCNameNestedClass)
test("TestObjCNameExact", testObjCNameExact)
test("TestObjCNameObject", testObjCNameObject)
test("TestObjCNameEnum", testObjCNameEnum)
test("TestObjCAvoidPreprocessorName", testObjCAvoidPreprocessorName)
}
}
@@ -0,0 +1,29 @@
/*
* 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.
*/
@file:OptIn(ExperimentalObjCName::class)
package objCNameA
import kotlin.experimental.ExperimentalObjCName
// https://youtrack.jetbrains.com/issue/KT-50767
@ObjCName("ObjCNameC1A")
class ObjCNameC1 {
fun foo(): String = "a"
}
// https://youtrack.jetbrains.com/issue/KT-48076
@ObjCName("with")
fun withUserId(userId: String): String = userId
// https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/3240586-supports
fun supports(@ObjCName(swiftName = "_") features: Boolean): Boolean = features
// https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/1518986-scanforperipherals
fun scanForPeripherals(@ObjCName("withServices") serviceUUIDs: Int, options: String): String = "$serviceUUIDs $options"
// https://developer.apple.com/documentation/corebluetooth/cbcentralmanager/3174844-registerforconnectionevents
fun registerForConnectionEvents(@ObjCName("withOptions", "options") options: String): String = "$options"
@@ -0,0 +1,86 @@
/*
* 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.
*/
@file:OptIn(ExperimentalObjCName::class)
package objCNameB
import kotlin.experimental.ExperimentalObjCName
// https://youtrack.jetbrains.com/issue/KT-50767
@ObjCName("ObjCNameC1B")
class ObjCNameC1 {
fun foo(): String = "b"
}
@ObjCName("MyObjCArray", "MySwiftArray")
class MyKotlinArray {
// https://developer.apple.com/documentation/foundation/nsarray/1409982-count
@ObjCName("count")
val size: Int = 0
// https://developer.apple.com/documentation/foundation/nsarray/1417076-index
@ObjCName(swiftName = "index")
fun indexOf(@ObjCName("object", "of") element: Int): Int = element
}
interface ObjCNameI1 {
@ObjCName("someOtherValue")
val someValue: Int
@ObjCName("someOtherFunction")
fun @receiver:ObjCName("receiver") Int.someFunction(@ObjCName("otherParam") param: Int): Int
}
fun @receiver:ObjCName("of") ObjCNameI1.getSomeValue(): Int = someValue
@ObjCName(swiftName = "SwiftNameC2")
class ObjCNameC2: ObjCNameI1 {
@ObjCName("ObjCNestedClass", "SwiftNestedClass")
class NestedClass {
var nestedValue: Int = 1
}
@ObjCName("ObjCExactNestedClass", "SwiftExactNestedClass", true)
class ExactNestedClass {
var nestedValue: Int = 1
}
override var someValue: Int = 0
override fun Int.someFunction(param: Int): Int = this * param
}
@ObjCName("ObjCNameC3", "SwiftNameC3", true)
class ObjCNameC3 {
@ObjCName("ObjCNestedClass", "SwiftNestedClass")
class NestedClass {
var nestedValue: Int = 2
}
}
private interface ObjCNameI2 {
fun @receiver:ObjCName("objCReceiver") Int.foo(@ObjCName("objCParam") param: Int): Int
}
class ObjCNameC4: ObjCNameI2 {
override fun Int.foo(param: Int): Int = this * param
}
@ObjCName("ObjCNameObjCObject", "ObjCNameSwiftObject")
object ObjCNameKotlinObject
@ObjCName("ObjCNameObjCEnum", "ObjCNameSwiftEnum")
enum class ObjCNameKotlinEnum {
@ObjCName("objcOne", "swiftOne")
KOTLIN_ONE,
@ObjCName("objcTwo", "companion")
kotlinTwo,
@ObjCName("objcThree", "swiftThree")
KotlinThree;
companion object {
fun foo(): Int = 0
}
}
class ObjCAvoidPreprocessorName(@property:ObjCName("time") @ObjCName("time") val __TIME__: Int)
@@ -0,0 +1,66 @@
package overrideKotlinMethods
import kotlin.test.*
internal interface OverrideKotlinMethods0<T> {
fun one(): T
}
internal interface OverrideKotlinMethods1<T> : OverrideKotlinMethods0<T>
interface OverrideKotlinMethods2 {
fun one(): Int
}
open class OverrideKotlinMethods3 {
internal open fun one(): Number = 3
}
open class OverrideKotlinMethods4 : OverrideKotlinMethods3(), OverrideKotlinMethods1<Int>, OverrideKotlinMethods2 {
override fun one(): Int = 2
}
interface OverrideKotlinMethods5 {
fun one(): Int
}
interface OverrideKotlinMethods6 : OverrideKotlinMethods5
// Using `Any` because Kotlin forbids internal type in public function signature.
@Throws(Throwable::class)
fun test0(obj: Any) {
val obj0 = obj as OverrideKotlinMethods0<*>
assertEquals(1, obj0.one())
}
// Using `Any` because Kotlin forbids internal type in public function signature.
@Throws(Throwable::class)
fun test1(obj: Any) {
val obj1 = obj as OverrideKotlinMethods1<*>
assertEquals(1, obj1.one())
}
@Throws(Throwable::class)
fun test2(obj: OverrideKotlinMethods2) {
assertEquals(1, obj.one())
}
@Throws(Throwable::class)
fun test3(obj: OverrideKotlinMethods3) {
assertEquals(1, obj.one())
}
@Throws(Throwable::class)
fun test4(obj: OverrideKotlinMethods4) {
assertEquals(1, obj.one())
}
@Throws(Throwable::class)
fun test5(obj: OverrideKotlinMethods5) {
assertEquals(1, obj.one())
}
@Throws(Throwable::class)
fun test6(obj: OverrideKotlinMethods6) {
assertEquals(1, obj.one())
}
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
class OverrideKotlinMethodsImpl : OverrideKotlinMethods4, OverrideKotlinMethods6 {
override func one() -> Int32 {
return 1
}
}
private func test1() throws {
let obj = OverrideKotlinMethodsImpl()
try OverrideKotlinMethodsKt.test0(obj: obj)
try OverrideKotlinMethodsKt.test1(obj: obj)
try OverrideKotlinMethodsKt.test2(obj: obj)
try OverrideKotlinMethodsKt.test3(obj: obj)
try OverrideKotlinMethodsKt.test4(obj: obj)
try OverrideKotlinMethodsKt.test5(obj: obj)
try OverrideKotlinMethodsKt.test6(obj: obj)
}
class OverrideKotlinMethodsTests : SimpleTestProvider {
override init() {
super.init()
test("Test1", test1)
}
}
@@ -0,0 +1,18 @@
package overrideMethodsOfAny
import kotlin.test.*
@Throws(Throwable::class)
fun test(obj: Any, other: Any, swift: Boolean) {
if (!swift) {
// Doesn't work for Swift, see https://youtrack.jetbrains.com/issue/KT-44613.
assertEquals(42, obj.hashCode())
assertTrue(obj.equals(other))
}
assertTrue(obj.equals(obj))
assertFalse(obj.equals(null))
assertFalse(obj.equals(Any()))
assertEquals("toString", obj.toString())
}
@@ -0,0 +1,43 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the LICENSE file.
*/
import Kt
private class SwiftOverridingMethodsOfAny : Hashable, Equatable, CustomStringConvertible {
var hashValue: Int { return 42 }
static func == (lhs: SwiftOverridingMethodsOfAny, rhs: SwiftOverridingMethodsOfAny) -> Bool {
return true
}
var description: String { return "toString" }
}
private func testSwift() throws {
try OverrideMethodsOfAnyKt.test(obj: SwiftOverridingMethodsOfAny(), other: SwiftOverridingMethodsOfAny(), swift: true)
}
private class ObjCOverridingMethodsOfAny : NSObject {
override var hash: Int { return 42 }
override func isEqual(_ other: Any?) -> Bool {
return other is ObjCOverridingMethodsOfAny
}
override var description: String { return "toString" }
}
private func testObjC() throws {
try OverrideMethodsOfAnyKt.test(obj: ObjCOverridingMethodsOfAny(), other: ObjCOverridingMethodsOfAny(), swift: false)
}
class OverrideMethodsOfAnyTests : SimpleTestProvider {
override init() {
super.init()
test("TestSwift", testSwift)
test("TestObjC", testObjC)
}
}
@@ -0,0 +1,10 @@
/*
* 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 recursiveGenericArguments
class RecList<T: List<T>>(val value: T)
class RecFunc<T : () -> T>(val value: T)
@@ -0,0 +1,17 @@
import Kt
#if !NO_GENERICS
private func testRecursiveGenericArguments() throws {
try assertTrue(type(of: RecList<NSArray>(value: []).value) == [Any].self)
}
#endif
class RecursiveGenericArgumentsTests : SimpleTestProvider {
override init() {
super.init()
#if !NO_GENERICS
test("TestRecursiveGenericArguments", testRecursiveGenericArguments)
#endif
}
}
@@ -0,0 +1,71 @@
/*
* 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 refined
import kotlin.experimental.ExperimentalObjCRefinement
@ExperimentalObjCRefinement
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.BINARY)
@MustBeDocumented
@HidesFromObjC
annotation class MyHiddenFromObjC
@ExperimentalObjCRefinement
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.BINARY)
@MustBeDocumented
@RefinesInSwift
annotation class MyShouldRefineInSwift
@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
fun foo(): Int = 1
@OptIn(ExperimentalObjCRefinement::class)
@ShouldRefineInSwift
fun fooRefined(): String = foo().toString()
@OptIn(ExperimentalObjCRefinement::class)
@MyHiddenFromObjC
fun myFoo(): Int = 2
@OptIn(ExperimentalObjCRefinement::class)
@MyShouldRefineInSwift
fun myFooRefined(): String = myFoo().toString()
@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
val bar: Int = 3
@OptIn(ExperimentalObjCRefinement::class)
@ShouldRefineInSwift
val barRefined: String get() = bar.toString()
@OptIn(ExperimentalObjCRefinement::class)
@MyHiddenFromObjC
val myBar: Int = 4
@OptIn(ExperimentalObjCRefinement::class)
@MyShouldRefineInSwift
val myBarRefined: String get() = myBar.toString()
open class RefinedClassA {
@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
open fun foo(): Int = 1
@OptIn(ExperimentalObjCRefinement::class)
@ShouldRefineInSwift
open fun fooRefined(): String = foo().toString()
}
class RefinedClassB: RefinedClassA() {
override fun foo(): Int = 2
override fun fooRefined(): String {
val foo = foo()
return "$foo$foo"
}
}
@@ -0,0 +1,50 @@
import Kt
extension RefinedKt {
static func foo() -> Int {
return Int(RefinedKt.__fooRefined())! * 2
}
static func myFoo() -> Int {
return Int(RefinedKt.__myFooRefined())! * 2
}
static var bar: Int {
return Int(RefinedKt.__barRefined)! * 2
}
static var myBar: Int {
return Int(RefinedKt.__myBarRefined)! * 2
}
}
extension RefinedClassA {
func foo() -> Int {
return Int(__fooRefined())! * 2
}
}
private func testSwiftRefinements() throws {
try assertEquals(actual: RefinedKt.foo(), expected: 2)
try assertEquals(actual: RefinedKt.bar, expected: 6)
}
private func testMySwiftRefinements() throws {
try assertEquals(actual: RefinedKt.myFoo(), expected: 4)
try assertEquals(actual: RefinedKt.myBar, expected: 8)
}
private func testInheritedRefinements() throws {
try assertEquals(actual: RefinedClassA().foo(), expected: 2)
try assertEquals(actual: RefinedClassB().foo(), expected: 44)
}
class RefinedTests : SimpleTestProvider {
override init() {
super.init()
test("TestSwiftRefinements", testSwiftRefinements)
test("TestMySwiftRefinements", testMySwiftRefinements)
test("TestInheritedRefinements", testInheritedRefinements)
}
}
@@ -0,0 +1,15 @@
/*
* Copyright 2010-2021 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 sealedClass
sealed class Person() {
data class User(val id: Int) : Person()
abstract class Worker() {
data class Employee(val id: Int) : Worker()
data class Contractor(val id: Int) : Worker()
}
}

Some files were not shown because too many files have changed in this diff Show More