From 536bfe5bf9eda627e96c5b113371b931ecd9ad22 Mon Sep 17 00:00:00 2001 From: Dmitriy Dolovov Date: Tue, 23 Nov 2021 14:59:52 +0300 Subject: [PATCH] [Native][tests] Use more compact paths to produced binaries --- native/native.tests/build.gradle.kts | 1 + .../konan/blackboxtest/CompressedNamesTest.kt | 92 +++++++++++++++++++ .../support/NativeBlackBoxTestSupport.kt | 18 ++-- .../blackboxtest/support/TestCompiler.kt | 6 +- .../support/util/CompressedNames.kt | 61 ++++++++++++ 5 files changed, 168 insertions(+), 10 deletions(-) create mode 100644 native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/CompressedNamesTest.kt create mode 100644 native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/util/CompressedNames.kt diff --git a/native/native.tests/build.gradle.kts b/native/native.tests/build.gradle.kts index e322c66d72b..968c550916a 100644 --- a/native/native.tests/build.gradle.kts +++ b/native/native.tests/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { testImplementation(project(":kotlin-reflect")) testImplementation(intellijCoreDep()) { includeJars("intellij-core") } testImplementation(intellijPluginDep("java")) + testImplementation(intellijDep()) { includeJars("commons-lang-2.4") } testImplementation(project(":kotlin-compiler-runner-unshaded")) testImplementation(projectTests(":compiler:tests-common")) testImplementation(projectTests(":compiler:tests-common-new")) diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/CompressedNamesTest.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/CompressedNamesTest.kt new file mode 100644 index 00000000000..27afb7e94fe --- /dev/null +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/CompressedNamesTest.kt @@ -0,0 +1,92 @@ +/* + * 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 org.jetbrains.kotlin.konan.blackboxtest + +import org.jetbrains.kotlin.konan.blackboxtest.support.util.compressedName +import org.jetbrains.kotlin.konan.blackboxtest.support.util.compressedPackageName +import org.jetbrains.kotlin.konan.blackboxtest.support.util.compressedSimpleName +import org.jetbrains.kotlin.konan.target.Architecture +import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.target.KonanTarget +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.Test +import kotlin.coroutines.Continuation + +class CompressedNamesTest { + @Test + fun targetNameCompression() { + val knownTargets: Set = KonanTarget.predefinedTargets.values.toSet() + + val compressedNameToTargets: Map = knownTargets.associateBy { it.compressedName } + val missingTargets: Set = compressedNameToTargets.values.toSet() - knownTargets + + assertTrue(missingTargets.isEmpty()) { "There are missing targets: $missingTargets" } + assertEquals(knownTargets.size, compressedNameToTargets.size) + + val shortestCompressedName = compressedNameToTargets.keys.minByOrNull { it.length }!! + assertTrue(shortestCompressedName.isNotEmpty()) { "Found empty compressed name: $shortestCompressedName" } + + val longestCompressedName = compressedNameToTargets.keys.maxByOrNull { it.length }!! + assertTrue(longestCompressedName.length < 6) { "Found too long compressed name: $longestCompressedName" } + } + + @Test + fun familyNameCompression() { + val knownFamilies: Set = Family.values().toSet() + + val compressedNameToFamily: Map = knownFamilies.associateBy { it.compressedName } + val missingFamilies: Set = compressedNameToFamily.values.toSet() - knownFamilies + + assertTrue(missingFamilies.isEmpty()) { "There are missing families: $missingFamilies" } + assertEquals(knownFamilies.size, compressedNameToFamily.size) + } + + @Test + fun architectureNameCompression() { + val knownArchitectures: Set = Architecture.values().toSet() + + val compressedNameToArchitecture: Map = knownArchitectures.associateBy { it.compressedName } + val missingArchitecture: Set = compressedNameToArchitecture.values.toSet() - knownArchitectures + + assertTrue(missingArchitecture.isEmpty()) { "There are missing architectures: $missingArchitecture" } + assertEquals(knownArchitectures.size, compressedNameToArchitecture.size) + + val nameLengths: Map> = compressedNameToArchitecture.keys.groupBy { it.length } + assertEquals(setOf(3), nameLengths.keys) { "Found compressed names with unexpected lengths: $nameLengths" } + } + + @Test + fun classNameCompression() { + assertEquals("LinHasMap", LinkedHashMap::class.java.compressedSimpleName) + assertEquals("Con", Continuation::class.java.compressedSimpleName) + assertEquals("AbsNatBlaBoxTes", AbstractNativeBlackBoxTest::class.java.compressedSimpleName) + } + + @Test + fun packageNameCompression() { + assertEquals( + "foo_bar_baz", + "foo.bar.baz".compressedPackageName + ) + assertEquals( + "foo_bar_baz_foo_bar_baz", + "foo.bar.baz.foo.bar.baz".compressedPackageName + ) + assertEquals( + "foo_bar_baz_foo_bar_baz_foo_bar_baz", + "foo.bar.baz.foo.bar.baz.foo.bar.baz".compressedPackageName + ) + assertEquals( + "foo_bar_baz_foo_bar_baz_foo_bar-de3b161b", + "foo.bar.baz.foo.bar.baz.foo.bar.baz.foo.bar.baz".compressedPackageName + ) + assertEquals( + "foo_bar_baz_foo_bar_baz_foo_bar-a4571752", + "foo.bar.baz.foo.bar.baz.foo.bar.baz.foo.bar.baz.foo.bar.baz".compressedPackageName + ) + } +} diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/NativeBlackBoxTestSupport.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/NativeBlackBoxTestSupport.kt index b622b4940a2..8ffe241d734 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/NativeBlackBoxTestSupport.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/NativeBlackBoxTestSupport.kt @@ -39,15 +39,19 @@ class NativeBlackBoxTestSupport : BeforeEachCallback { private val NAMESPACE = ExtensionContext.Namespace.create(NativeBlackBoxTestSupport::class.java.simpleName) /** Creates a single instance of [TestRunProvider] per test class. */ - private fun ExtensionContext.getOrCreateTestRunProvider(): TestRunProvider = - root.getStore(NAMESPACE).getOrComputeIfAbsent(enclosingTestClass.sanitizedName) { sanitizedName -> + private fun ExtensionContext.getOrCreateTestRunProvider(): TestRunProvider { + val enclosingTestClass = enclosingTestClass + + return root.getStore(NAMESPACE).getOrComputeIfAbsent(enclosingTestClass.sanitizedName) { val globalEnvironment = getOrCreateGlobalEnvironment() val testRoots = computeTestRoots() + val uniqueEnclosingClassDirName = globalEnvironment.target.compressedName + "_" + enclosingTestClass.compressedSimpleName + val testSourcesDir = globalEnvironment.baseBuildDir - .resolve("blackbox-test-sources") - .resolve(sanitizedName) + .resolve("bbtest.src") + .resolve(uniqueEnclosingClassDirName) .ensureExistsAndIsEmptyDirectory() // Clean-up the directory with all potentially stale generated sources. val sharedSourcesDir = testSourcesDir @@ -55,9 +59,8 @@ class NativeBlackBoxTestSupport : BeforeEachCallback { .ensureExistsAndIsEmptyDirectory() val testBinariesDir = globalEnvironment.baseBuildDir - .resolve("blackbox-test-binaries") - .resolve(globalEnvironment.target.name) - .resolve(sanitizedName) + .resolve("bbtest.bin") + .resolve(uniqueEnclosingClassDirName) .ensureExistsAndIsEmptyDirectory() // Clean-up the directory with all potentially stale artifacts. val sharedBinariesDir = testBinariesDir @@ -77,6 +80,7 @@ class NativeBlackBoxTestSupport : BeforeEachCallback { TestRunProvider(environment, testCaseGroupProvider) }.cast() + } private fun ExtensionContext.getOrCreateGlobalEnvironment(): GlobalTestEnvironment = root.getStore(NAMESPACE).getOrComputeIfAbsent(GlobalTestEnvironment::class.java.sanitizedName) { diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestCompiler.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestCompiler.kt index 858b6d5d844..a1f594712d6 100644 --- a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestCompiler.kt +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/TestCompiler.kt @@ -99,7 +99,7 @@ internal class TestCompilationFactory(private val environment: TestEnvironment) private fun singleModuleArtifactFile(module: TestModule.Exclusive, extension: String): File { val artifactFileName = buildString { - append(module.testCase.nominalPackageName.replace('.', '_')).append('.') + append(module.testCase.nominalPackageName.compressedPackageName).append('.') if (extension == "klib") append(module.name).append('.') append(extension) } @@ -129,7 +129,7 @@ internal class TestCompilationFactory(private val environment: TestEnvironment) append(prefix).append('-') if (commonPackageName != null) - append(commonPackageName.replace('.', '_')).append('-') + append(commonPackageName.compressedPackageName).append('-') append(prettyHash(hash)) @@ -141,7 +141,7 @@ internal class TestCompilationFactory(private val environment: TestEnvironment) private fun artifactDirForPackageName(packageName: PackageFQN?): File { val baseDir = environment.testBinariesDir - val outputDir = if (packageName != null) baseDir.resolve(packageName.replace('.', '_')) else baseDir + val outputDir = if (packageName != null) baseDir.resolve(packageName.compressedPackageName) else baseDir outputDir.mkdirs() diff --git a/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/util/CompressedNames.kt b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/util/CompressedNames.kt new file mode 100644 index 00000000000..336c8ccce2f --- /dev/null +++ b/native/native.tests/tests/org/jetbrains/kotlin/konan/blackboxtest/support/util/CompressedNames.kt @@ -0,0 +1,61 @@ +/* + * 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 org.jetbrains.kotlin.konan.blackboxtest.support.util + +import org.apache.commons.lang.StringUtils.splitByCharacterTypeCamelCase +import org.jetbrains.kotlin.konan.blackboxtest.support.PackageFQN +import org.jetbrains.kotlin.konan.target.Architecture +import org.jetbrains.kotlin.konan.target.Family +import org.jetbrains.kotlin.konan.target.KonanTarget + +internal val KonanTarget.compressedName: String + get() = buildString { + append(family.compressedName) + name.splitToSequence('_') + .drop(1) + .filter { it.none(Char::isDigit) } + .forEach { append(it[0]) } + append(architecture.compressedName) + } + +internal val Family.compressedName: Char + get() = when (this) { + Family.OSX -> 'o' + Family.IOS -> 'i' + Family.TVOS -> 't' + Family.WATCHOS -> 'w' + Family.LINUX -> 'l' + Family.MINGW -> 'm' + Family.ANDROID -> 'a' + Family.WASM -> 'j' // because 'w', 'a' and 'm' are already occupied + Family.ZEPHYR -> 'z' + } + +internal val Architecture.compressedName: String + get() = when (this) { + Architecture.X64 -> "x64" + Architecture.X86 -> "x86" + Architecture.ARM64 -> "a64" + Architecture.ARM32 -> "a32" + Architecture.MIPS32 -> "m32" + Architecture.MIPSEL32 -> "e32" + Architecture.WASM32 -> "w32" + } + +internal val Class<*>.compressedSimpleName: String + get() = splitByCharacterTypeCamelCase(simpleName).joinToString("") { it.take(3) } + +internal val PackageFQN.compressedPackageName: String + get() { + val sanitizedName = replace('.', '_') + return if (sanitizedName.length > COMPRESSED_PACKAGE_FQN_MAX_LENGTH) { + val suffix = "-" + prettyHash(sanitizedName.hashCode()) + sanitizedName.substring(0, COMPRESSED_PACKAGE_FQN_MAX_LENGTH - suffix.length) + suffix + } else + sanitizedName + } + +private const val COMPRESSED_PACKAGE_FQN_MAX_LENGTH = 40