From 4d7f39b51da4955cf9a9cbdd5c704e1b57a89b42 Mon Sep 17 00:00:00 2001 From: Svyatoslav Scherbina Date: Mon, 14 Oct 2019 13:15:29 +0300 Subject: [PATCH] Add test for using multiple Kotlin frameworks in single application --- backend.native/tests/build.gradle | 36 +++++++++++++ .../framework/multiple/framework1/first.kt | 20 ++++++++ .../framework/multiple/framework1/test.kt | 10 ++++ .../framework/multiple/framework2/second.kt | 18 +++++++ .../framework/multiple/framework2/test.kt | 10 ++++ .../tests/framework/multiple/multiple.swift | 51 +++++++++++++++++++ .../tests/framework/multiple/shared/shared.kt | 11 ++++ 7 files changed, 156 insertions(+) create mode 100644 backend.native/tests/framework/multiple/framework1/first.kt create mode 100644 backend.native/tests/framework/multiple/framework1/test.kt create mode 100644 backend.native/tests/framework/multiple/framework2/second.kt create mode 100644 backend.native/tests/framework/multiple/framework2/test.kt create mode 100644 backend.native/tests/framework/multiple/multiple.swift create mode 100644 backend.native/tests/framework/multiple/shared/shared.kt diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index fb080741510..2007f041629 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -3735,6 +3735,42 @@ if (isAppleTarget(project)) { } swiftSources = ['framework/stdlib/stdlib.swift'] } + + task testMultipleFrameworks(type: FrameworkTest) { + testName = "MultipleFrameworks" + final String firstFrameworkName = 'First' + final String secondFrameworkName = 'Second' + frameworkNames = [firstFrameworkName, secondFrameworkName] + + final String dir = "$testOutputFramework/$testName" + + konanArtifacts { + framework(firstFrameworkName, targets: [ targetName ]) { + srcDir 'framework/multiple/framework1' + srcDir 'framework/multiple/shared' + baseDir dir + + if (!useCustomDist) { + dependsOn ":${targetName}CrossDistRuntime", ':commonDistRuntime', ':distCompiler' + } + + extraOpts project.globalTestArgs + } + + framework(secondFrameworkName, targets: [ targetName ]) { + srcDir 'framework/multiple/framework2' + srcDir 'framework/multiple/shared' + baseDir dir + + if (!useCustomDist) { + dependsOn ":${targetName}CrossDistRuntime", ':commonDistRuntime', ':distCompiler' + } + + extraOpts project.globalTestArgs + } + } + swiftSources = ['framework/multiple/multiple.swift'] + } } /** diff --git a/backend.native/tests/framework/multiple/framework1/first.kt b/backend.native/tests/framework/multiple/framework1/first.kt new file mode 100644 index 00000000000..ae516a444e4 --- /dev/null +++ b/backend.native/tests/framework/multiple/framework1/first.kt @@ -0,0 +1,20 @@ +/* + * 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 +} + +class C + +fun getUnit(): Unit? = Unit \ No newline at end of file diff --git a/backend.native/tests/framework/multiple/framework1/test.kt b/backend.native/tests/framework/multiple/framework1/test.kt new file mode 100644 index 00000000000..c25f00f106f --- /dev/null +++ b/backend.native/tests/framework/multiple/framework1/test.kt @@ -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" \ No newline at end of file diff --git a/backend.native/tests/framework/multiple/framework2/second.kt b/backend.native/tests/framework/multiple/framework2/second.kt new file mode 100644 index 00000000000..aa03741da93 --- /dev/null +++ b/backend.native/tests/framework/multiple/framework2/second.kt @@ -0,0 +1,18 @@ +/* + * 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() + +class C + +fun isUnit(obj: Any?): Boolean = (obj === Unit) \ No newline at end of file diff --git a/backend.native/tests/framework/multiple/framework2/test.kt b/backend.native/tests/framework/multiple/framework2/test.kt new file mode 100644 index 00000000000..4a424e63fc4 --- /dev/null +++ b/backend.native/tests/framework/multiple/framework2/test.kt @@ -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" \ No newline at end of file diff --git a/backend.native/tests/framework/multiple/multiple.swift b/backend.native/tests/framework/multiple/multiple.swift new file mode 100644 index 00000000000..e1f6cb6fccf --- /dev/null +++ b/backend.native/tests/framework/multiple/multiple.swift @@ -0,0 +1,51 @@ +/* + * 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 testIsolation() 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()) +} + +class MultipleFrameworksTests : TestProvider { + var tests: [TestCase] = [] + + init() { + tests = [ + TestCase(name: "TestClashingNames", method: withAutorelease(testClashingNames)), + TestCase(name: "TestInteraction", method: withAutorelease(testInteraction)), + TestCase(name: "TestIsolation", method: withAutorelease(testIsolation)), + ] + providers.append(self) + } + +} \ No newline at end of file diff --git a/backend.native/tests/framework/multiple/shared/shared.kt b/backend.native/tests/framework/multiple/shared/shared.kt new file mode 100644 index 00000000000..dab9d5d8303 --- /dev/null +++ b/backend.native/tests/framework/multiple/shared/shared.kt @@ -0,0 +1,11 @@ +import kotlin.native.concurrent.Worker + +object RuntimeState { + fun produceChange() { + Worker.current.executeAfter {} + } + + fun consumeChange(): Boolean { + return Worker.current.processQueue() + } +} \ No newline at end of file