From 898dd02d29737587bb187c7e4ca4271ae0f8107a Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Thu, 12 Jan 2023 13:08:57 +0200 Subject: [PATCH] [K/N][cinterop] Indexer unit-tests of `objcClassesIncludingCategories` --- .../interop/gen/IncludeCategoriesTests.kt | 74 +++++++++++++++++++ .../native/interop/gen/InteropTestsBase.kt | 41 +++++++++- .../resources/IncludeCategories/header1.h | 19 +++++ .../resources/IncludeCategories/header2.h | 10 +++ .../IncludeCategories/includeCategory0.def | 4 + .../IncludeCategories/includeCategory1.def | 7 ++ .../IncludeCategories/includeCategory2.def | 7 ++ 7 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/IncludeCategoriesTests.kt create mode 100644 kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/header1.h create mode 100644 kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/header2.h create mode 100644 kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/includeCategory0.def create mode 100644 kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/includeCategory1.def create mode 100644 kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/includeCategory2.def diff --git a/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/IncludeCategoriesTests.kt b/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/IncludeCategoriesTests.kt new file mode 100644 index 00000000000..621be82ac4d --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/IncludeCategoriesTests.kt @@ -0,0 +1,74 @@ +/* + * 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 org.jetbrains.kotlin.native.interop.gen + +import org.jetbrains.kotlin.konan.target.HostManager +import org.jetbrains.kotlin.native.interop.indexer.IndexerResult +import org.junit.Assume +import kotlin.test.* + +// Note: A better place for these tests would be Indexer module. +// But infrastructure that is required for these tests belongs to StubGenerator. +class IncludeCategoriesTests : InteropTestsBase() { + + private fun IndexerResult.getObjCClass(name: String) = + index.objCClasses.first { it.name == name } + + private fun IndexerResult.getObjCCategory(name: String) = + index.objCCategories.first { it.name == name } + + @BeforeTest + fun checkPlatform() { + Assume.assumeTrue(HostManager.hostIsMac) + } + + @Test + fun `smoke 0`() { + val index = buildNativeIndex("IncludeCategories", "includeCategory0.def") + val myClass = index.getObjCClass("MyClass") + val myClassCategories = myClass.includedCategories.map { it.name } + assertContains(myClassCategories, "IncludeCategory") + assertContains(myClassCategories, "IncludeCategory2") + } + + @Test + fun `only specific classes include categories`() { + val index = buildNativeIndex("IncludeCategories", "includeCategory0.def") + val skipClass = index.getObjCClass("SkipClass") + assertTrue(skipClass.includedCategories.isEmpty()) + } + + @Test + fun `category from another header is not included`() { + val index = buildNativeIndex("IncludeCategories", "includeCategory0.def") + val myClass = index.getObjCClass("MyClass") + val myClassCategories = myClass.includedCategories.map { it.name } + assertContains(myClassCategories, "IncludeCategory") + assertFalse("SkipCategory" in myClassCategories) + } + + @Test + fun `external category is not included into index`() { + val dependencyIndex = buildNativeIndex("IncludeCategories", "includeCategory0.def") + val index = buildNativeIndex("IncludeCategories", "includeCategory1.def", mockImports(dependencyIndex)) + + val derivedClass = index.getObjCClass("Derived") + val myClass = derivedClass.baseClass!! + assertEquals("MyClass", myClass.name) + assertFalse(myClass in index.index.objCClasses) + val myClassCategories = myClass.includedCategories + assertTrue(myClassCategories.isNotEmpty()) + assertTrue(myClassCategories.all { it !in index.index.objCCategories }) + } + + @Test + fun `category is not included into dependency class`() { + val dependencyIndex = buildNativeIndex("IncludeCategories", "includeCategory0.def") + val index = buildNativeIndex("IncludeCategories", "includeCategory2.def", mockImports(dependencyIndex)) + val category = index.getObjCCategory("ChildCategory") + assertFalse(category in category.clazz.includedCategories) + } +} \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropTestsBase.kt b/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropTestsBase.kt index ee37dded10c..557c9c844e4 100644 --- a/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropTestsBase.kt +++ b/kotlin-native/Interop/StubGenerator/src/test/kotlin/org/jetbrains/kotlin/native/interop/gen/InteropTestsBase.kt @@ -12,10 +12,14 @@ import org.jetbrains.kotlin.konan.util.NativeMemoryAllocator import org.jetbrains.kotlin.native.interop.gen.jvm.KotlinPlatform import org.jetbrains.kotlin.native.interop.gen.jvm.buildNativeLibrary import org.jetbrains.kotlin.native.interop.gen.jvm.prepareTool +import org.jetbrains.kotlin.native.interop.indexer.HeaderId +import org.jetbrains.kotlin.native.interop.indexer.IndexerResult +import org.jetbrains.kotlin.native.interop.indexer.Location import org.jetbrains.kotlin.native.interop.indexer.NativeLibrary import org.jetbrains.kotlin.native.interop.tool.CInteropArguments import kotlin.test.* import java.io.File +import java.nio.file.Paths abstract class InteropTestsBase { init { @@ -47,7 +51,7 @@ abstract class InteropTestsBase { } } - protected fun buildNativeLibraryFrom(defFile: File, headersDirectory: File): NativeLibrary { + protected fun buildNativeLibraryFrom(defFile: File, headersDirectory: File, imports: Imports = ImportsMock()): NativeLibrary { val tool = prepareTool(HostManager.hostName, KotlinPlatform.NATIVE, runFromDaemon = true) val cinteropArguments = CInteropArguments() cinteropArguments.argParser.parse(arrayOf( @@ -57,7 +61,40 @@ abstract class InteropTestsBase { tool, DefFile(defFile, tool.substitutions), cinteropArguments, - ImportsImpl(emptyMap()) + imports ) } + + protected fun getTestResources(directoryName: String): File { + val resource = this::class.java.getResource("/$directoryName") + return Paths.get(resource.toURI()).toFile() + } + + protected fun buildNativeLibraryFrom(directoryName: String, defFileName: String, imports: Imports = ImportsMock()): NativeLibrary { + val directory = getTestResources(directoryName) + val defFile = File(directory, defFileName) + return buildNativeLibraryFrom(defFile, directory, imports) + } + + protected fun buildNativeIndex(directoryName: String, defFileName: String, imports: Imports = ImportsMock()): IndexerResult { + val library = buildNativeLibraryFrom(directoryName, defFileName, imports) + return org.jetbrains.kotlin.native.interop.indexer.buildNativeIndex(library, verbose = false) + } + + protected fun mockImports(dependencyIndex: IndexerResult, packageName: String = "dependencyLibrary"): Imports { + return ImportsMock(dependencyIndex.index.includedHeaders.associateWith { packageName }) + } + + /** + * Trivial implementation of [Imports] interface, untied from KonanLibrary. + */ + protected class ImportsMock(private val headerToPackage: Map = emptyMap()) : Imports { + override fun getPackage(location: Location): String? { + return headerToPackage[location.headerId] + } + + override fun isImported(headerId: HeaderId): Boolean { + return headerId in headerToPackage + } + } } \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/header1.h b/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/header1.h new file mode 100644 index 00000000000..65d5fb09b92 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/header1.h @@ -0,0 +1,19 @@ +#ifndef _HEADER1_ +#define _HEADER1_ + +@interface MyClass +@end + +@interface MyClass(IncludeCategory) +@end + +@interface MyClass(IncludeCategory2) +@end + +@interface SkipClass +@end + +@interface SkipClass(IncludeCategory) +@end + +#endif diff --git a/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/header2.h b/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/header2.h new file mode 100644 index 00000000000..ac6f9fadb63 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/header2.h @@ -0,0 +1,10 @@ +#ifndef _HEADER2_ +#define _HEADER2_ + +#include "header1.h" + +@interface MyClass(SkipCategory) +- (void)skipMethod; +@end + +#endif \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/includeCategory0.def b/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/includeCategory0.def new file mode 100644 index 00000000000..f44c8d7235c --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/includeCategory0.def @@ -0,0 +1,4 @@ +language = Objective-C +headers = header1.h header2.h + +objcClassesIncludingCategories = MyClass \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/includeCategory1.def b/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/includeCategory1.def new file mode 100644 index 00000000000..b60357176af --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/includeCategory1.def @@ -0,0 +1,7 @@ +language = Objective-C +objcClassesIncludingCategories = MyClass +--- +#include + +@interface Derived : MyClass +@end \ No newline at end of file diff --git a/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/includeCategory2.def b/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/includeCategory2.def new file mode 100644 index 00000000000..f1c341fc141 --- /dev/null +++ b/kotlin-native/Interop/StubGenerator/src/test/resources/IncludeCategories/includeCategory2.def @@ -0,0 +1,7 @@ +language = Objective-C +objcClassesIncludingCategories = MyClass +--- +#include + +@interface MyClass(ChildCategory) +@end \ No newline at end of file