[ObjCExport] Implement 'TodoAnalysisApi' annotation and run AA based tests as part of ':native:objcexport-header-generator:check'
^KT-65281 Fixed ^KT-65108 Fixed
This commit is contained in:
committed by
Space Team
parent
55adeba011
commit
0db8931026
@@ -59,3 +59,31 @@ both implementations.
|
||||
```
|
||||
|
||||
Note: Since the Analysis Api implementation is WIP yet, this test can be used for debugging, but is not fully implemented yet.
|
||||
|
||||
### CI setup and 'TodoAnalysisApi'
|
||||
As explained previously, tests in :native:objcexport-header-generator will be able to run against K1 and the AA implementation.
|
||||
The CI will now run both cases. However, some tests are not yet expected to pass for the newer AA based implementation.
|
||||
In this case the test can be marked as 'todo' using the `@TodoAnalysisApi` annotation.
|
||||
|
||||
Example
|
||||
```kotlin
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun myTest() {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
This annotation will
|
||||
- Ignore test the test failure for the AA based implementation on the CI
|
||||
- Mark the displayName of the test with 'TODO' (e.g. `[AA] myTest // TODO`)
|
||||
|
||||
Note:
|
||||
- The test will still fail locally (developer setup, not marked as CI).
|
||||
- If the annotation is still present, but the test is successful on CI, then an error is emitted that reminds you about removing the annotation
|
||||
|
||||
The behaviour of the CI can be replicated by passing a Gradle property like
|
||||
```text
|
||||
./gradlew :native:objcexport-header-generator:check -Pci
|
||||
// ^
|
||||
```
|
||||
@@ -45,21 +45,17 @@ tasks.test.configure {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
nativeTest("testK1", tag = null, requirePlatformLibs = true) {
|
||||
useJUnitPlatform()
|
||||
enableJunit5ExtensionsAutodetection()
|
||||
objCExportHeaderGeneratorTest("testK1", testDisplayNameTag = "K1") {
|
||||
classpath += k1TestRuntimeClasspath
|
||||
}
|
||||
|
||||
nativeTest("testAnalysisApi", tag = null, requirePlatformLibs = true) {
|
||||
useJUnitPlatform()
|
||||
enableJunit5ExtensionsAutodetection()
|
||||
testClassesDirs += files(sourceSets.test.map { it.output.classesDirs })
|
||||
objCExportHeaderGeneratorTest("testAnalysisApi", testDisplayNameTag = "AA") {
|
||||
classpath += analysisApiRuntimeClasspath
|
||||
}
|
||||
|
||||
tasks.check.configure {
|
||||
dependsOn("testK1")
|
||||
dependsOn("testAnalysisApi")
|
||||
dependsOn(":native:objcexport-header-generator-k1:check")
|
||||
dependsOn(":native:objcexport-header-generator-analysis-api:check")
|
||||
}
|
||||
|
||||
@@ -27,7 +27,4 @@ sourceSets {
|
||||
|
||||
testsJar()
|
||||
|
||||
nativeTest("test", tag = null, requirePlatformLibs = true) {
|
||||
useJUnitPlatform()
|
||||
enableJunit5ExtensionsAutodetection()
|
||||
}
|
||||
objCExportHeaderGeneratorTest("test")
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2024 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 org.jetbrains.kotlin.objcexport.testUtils
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.testUtils.TodoAnalysisApi
|
||||
import org.jetbrains.kotlin.backend.konan.testUtils.isCI
|
||||
import org.junit.AssumptionViolatedException
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback
|
||||
import org.junit.jupiter.api.extension.ExtensionContext
|
||||
import org.junit.jupiter.api.extension.TestExecutionExceptionHandler
|
||||
import kotlin.jvm.optionals.getOrNull
|
||||
|
||||
internal class TodoAnalysisApiTestExecutionExceptionHandler : TestExecutionExceptionHandler, AfterEachCallback {
|
||||
override fun handleTestExecutionException(context: ExtensionContext, throwable: Throwable) {
|
||||
val element = context.element.getOrNull() ?: return
|
||||
if (element.isAnnotationPresent(TodoAnalysisApi::class.java)) {
|
||||
val message = "Test is marked as 'Todo' for Analysis Api"
|
||||
if (isCI) {
|
||||
throwable.printStackTrace(System.err)
|
||||
throw AssumptionViolatedException(message, throwable)
|
||||
} else {
|
||||
context.publishReportEntry(message)
|
||||
System.err.println(message)
|
||||
}
|
||||
}
|
||||
|
||||
throw throwable
|
||||
}
|
||||
|
||||
override fun afterEach(context: ExtensionContext) {
|
||||
val element = context.element.getOrNull() ?: return
|
||||
if (element.isAnnotationPresent(TodoAnalysisApi::class.java) && context.executionException.getOrNull() == null) {
|
||||
val report: (String) -> Unit = if (isCI) ::error else System.err::println
|
||||
report("Test: ${context.displayName} was marked as 'Todo' but executed successfully")
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -5,3 +5,4 @@
|
||||
org.jetbrains.kotlin.objcexport.testUtils.AnalysisApiHeaderGeneratorExtension
|
||||
org.jetbrains.kotlin.objcexport.testUtils.InlineSourceCodeAnalysisExtension
|
||||
org.jetbrains.kotlin.objcexport.testUtils.AnalysisApiBaseDeclarationsGeneratorExtension
|
||||
org.jetbrains.kotlin.objcexport.testUtils.TodoAnalysisApiTestExecutionExceptionHandler
|
||||
@@ -25,7 +25,4 @@ kotlin {
|
||||
|
||||
testsJar()
|
||||
|
||||
nativeTest("test", tag = null, requirePlatformLibs = true) {
|
||||
useJUnitPlatform()
|
||||
enableJunit5ExtensionsAutodetection()
|
||||
}
|
||||
objCExportHeaderGeneratorTest("test")
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010-2024 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 org.jetbrains.kotlin.backend.konan.testUtils
|
||||
|
||||
import org.junit.jupiter.api.DisplayNameGenerator
|
||||
import java.lang.reflect.Method
|
||||
|
||||
class TestDisplayNameGenerator : DisplayNameGenerator {
|
||||
private val tag = System.getProperty("testDisplayName.tag")
|
||||
private val default = DisplayNameGenerator.Standard()
|
||||
|
||||
override fun generateDisplayNameForClass(testClass: Class<*>?): String {
|
||||
return default.generateDisplayNameForClass(testClass)
|
||||
}
|
||||
|
||||
override fun generateDisplayNameForNestedClass(nestedClass: Class<*>?): String {
|
||||
return default.generateDisplayNameForNestedClass(nestedClass)
|
||||
}
|
||||
|
||||
override fun generateDisplayNameForMethod(testClass: Class<*>?, testMethod: Method?): String {
|
||||
val defaultName = default.generateDisplayNameForMethod(testClass, testMethod)
|
||||
val isTodo = testMethod?.isAnnotationPresent(TodoAnalysisApi::class.java) ?: false && tag == "AA"
|
||||
|
||||
return buildString {
|
||||
if (tag != null) append("[$tag] ")
|
||||
append(defaultName)
|
||||
if (isTodo) append(" // TODO")
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Copyright 2010-2024 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 org.jetbrains.kotlin.backend.konan.testUtils
|
||||
|
||||
annotation class TodoAnalysisApi
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright 2010-2024 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 org.jetbrains.kotlin.backend.konan.testUtils
|
||||
|
||||
/**
|
||||
* Indicates if the tests are currently executed on CI like teamcity
|
||||
*/
|
||||
val isCI = System.getProperty("is.ci")?.toBoolean() ?: throw RuntimeException("Missing 'is.ci' System property")
|
||||
+3
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.tests
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCTopLevel
|
||||
import org.jetbrains.kotlin.backend.konan.objcexport.StubRenderer
|
||||
import org.jetbrains.kotlin.backend.konan.testUtils.TodoAnalysisApi
|
||||
import org.jetbrains.kotlin.backend.konan.testUtils.baseDeclarationsDir
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.junit.jupiter.api.Test
|
||||
@@ -25,11 +26,13 @@ class ObjCExportBaseDeclarationsTest(
|
||||
) {
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - noTopLevelPrefix`() {
|
||||
doTest(baseDeclarationsDir.resolve("!noTopLevelPrefix.h"), "")
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - topLevelPrefix`() {
|
||||
doTest(baseDeclarationsDir.resolve("!topLevelPrefix.h"), "MyTopLevelPrefix")
|
||||
}
|
||||
|
||||
+5
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.backend.konan.tests
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.testUtils.HeaderGenerator
|
||||
import org.jetbrains.kotlin.backend.konan.testUtils.TodoAnalysisApi
|
||||
import org.jetbrains.kotlin.backend.konan.testUtils.forwardDeclarationsDir
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.junit.jupiter.api.Test
|
||||
@@ -17,21 +18,25 @@ class ObjCExportForwardDeclarationsTest(
|
||||
) {
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - function returning interface`() {
|
||||
doTest(forwardDeclarationsDir.resolve("functionReturningInterface"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - function returning class`() {
|
||||
doTest(forwardDeclarationsDir.resolve("functionReturningClass"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - property returning interface`() {
|
||||
doTest(forwardDeclarationsDir.resolve("propertyReturningInterface"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - property returning class`() {
|
||||
doTest(forwardDeclarationsDir.resolve("propertyReturningClass"))
|
||||
}
|
||||
|
||||
+15
-1
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.konan.tests
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.testUtils.HeaderGenerator
|
||||
import org.jetbrains.kotlin.backend.konan.testUtils.HeaderGenerator.Configuration
|
||||
import org.jetbrains.kotlin.backend.konan.testUtils.TodoAnalysisApi
|
||||
import org.jetbrains.kotlin.backend.konan.testUtils.headersTestDataDir
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.junit.jupiter.api.Test
|
||||
@@ -30,7 +31,7 @@ import kotlin.test.fail
|
||||
* 3) Create a test function and call ` doTest(headersTestDataDir.resolve("myTest"))`
|
||||
* 4) The first invocation will fail the test, but generates the header that can be checked in (if sufficient)
|
||||
*/
|
||||
class ObjCExportHeaderGeneratorTest(val generator: HeaderGenerator) {
|
||||
class ObjCExportHeaderGeneratorTest(private val generator: HeaderGenerator) {
|
||||
|
||||
@Test
|
||||
fun `test - simpleClass`() {
|
||||
@@ -43,6 +44,7 @@ class ObjCExportHeaderGeneratorTest(val generator: HeaderGenerator) {
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - simpleEnumClass`() {
|
||||
doTest(headersTestDataDir.resolve("simpleEnumClass"))
|
||||
}
|
||||
@@ -63,16 +65,19 @@ class ObjCExportHeaderGeneratorTest(val generator: HeaderGenerator) {
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - sameClassNameInDifferentPackage`() {
|
||||
doTest(headersTestDataDir.resolve("sameClassNameInDifferentPackage"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - nestedClass`() {
|
||||
doTest(headersTestDataDir.resolve("nestedClass"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - samePropertyAndFunctionName`() {
|
||||
doTest(headersTestDataDir.resolve("samePropertyAndFunctionName"))
|
||||
}
|
||||
@@ -88,11 +93,13 @@ class ObjCExportHeaderGeneratorTest(val generator: HeaderGenerator) {
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - classWithObjCNameAnnotation`() {
|
||||
doTest(headersTestDataDir.resolve("classWithObjCNameAnnotation"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - functionWithObjCNameAnnotation`() {
|
||||
doTest(headersTestDataDir.resolve("functionWithObjCNameAnnotation"))
|
||||
}
|
||||
@@ -108,6 +115,7 @@ class ObjCExportHeaderGeneratorTest(val generator: HeaderGenerator) {
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - functionWithThrowsAnnotation`() {
|
||||
doTest(headersTestDataDir.resolve("functionWithThrowsAnnotation"))
|
||||
}
|
||||
@@ -118,11 +126,13 @@ class ObjCExportHeaderGeneratorTest(val generator: HeaderGenerator) {
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - functionWithErrorTypeAndFrameworkName`() {
|
||||
doTest(headersTestDataDir.resolve("functionWithErrorTypeAndFrameworkName"), Configuration(frameworkName = "shared"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - kdocWithBlockTags`() {
|
||||
doTest(headersTestDataDir.resolve("kdocWithBlockTags"))
|
||||
}
|
||||
@@ -143,16 +153,19 @@ class ObjCExportHeaderGeneratorTest(val generator: HeaderGenerator) {
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - parameterWithMustBeDocumentedAnnotation`() {
|
||||
doTest(headersTestDataDir.resolve("parameterWithMustBeDocumentedAnnotation"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - receiverWithMustBeDocumentedAnnotation`() {
|
||||
doTest(headersTestDataDir.resolve("receiverWithMustBeDocumentedAnnotation"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - dispatchAndExtensionReceiverWithMustBeDocumentedAnnotation`() {
|
||||
doTest(headersTestDataDir.resolve("dispatchAndExtensionReceiverWithMustBeDocumentedAnnotation"))
|
||||
}
|
||||
@@ -168,6 +181,7 @@ class ObjCExportHeaderGeneratorTest(val generator: HeaderGenerator) {
|
||||
}
|
||||
|
||||
@Test
|
||||
@TodoAnalysisApi
|
||||
fun `test - topLevelFunctionWithNumberReturn`() {
|
||||
doTest(headersTestDataDir.resolve("topLevelFunctionWithNumberReturn"))
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
junit.jupiter.displayname.generator.default=org.jetbrains.kotlin.backend.konan.testUtils.TestDisplayNameGenerator
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
|
||||
/*
|
||||
* Copyright 2010-2024 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Wrapper for [nativeTest] which helps to apply defaults expected by
|
||||
* projects under ':native:objcexport-header-generator:*'
|
||||
*/
|
||||
fun Project.objCExportHeaderGeneratorTest(
|
||||
taskName: String,
|
||||
testDisplayNameTag: String? = null,
|
||||
configure: Test.() -> Unit = {},
|
||||
) = nativeTest(
|
||||
taskName = taskName,
|
||||
tag = null,
|
||||
requirePlatformLibs = false,
|
||||
) {
|
||||
useJUnitPlatform()
|
||||
enableJunit5ExtensionsAutodetection()
|
||||
systemProperty("is.ci", kotlinBuildProperties.isTeamcityBuild || project.providers.gradleProperty("ci").isPresent)
|
||||
if (testDisplayNameTag != null) {
|
||||
systemProperty("testDisplayName.tag", testDisplayNameTag)
|
||||
}
|
||||
configure()
|
||||
}
|
||||
Reference in New Issue
Block a user