Split android box tests by flavours
This commit is contained in:
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<option name="DEFAULT_COMPILER" value="Javac" />
|
||||
<excludeFromCompile>
|
||||
<directory url="file://$PROJECT_DIR$/gen" includeSubdirectories="true" />
|
||||
</excludeFromCompile>
|
||||
</component>
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/android-module.iml" filepath="$PROJECT_DIR$/android_module.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="Android_SDK" project-jdk-type="Android SDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
@@ -5,9 +5,8 @@ buildscript {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.2.1'
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.3.2'
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
@@ -31,7 +30,6 @@ android {
|
||||
versionName "1.0"
|
||||
testApplicationId "org.jetbrains.kotlin.android.tests.gradle"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
}
|
||||
buildTypes {
|
||||
debug {
|
||||
@@ -62,6 +60,19 @@ android {
|
||||
resultsDir = "build/test/results"
|
||||
}
|
||||
|
||||
|
||||
flavorDimensions "box"
|
||||
|
||||
productFlavors {
|
||||
ktest0 {
|
||||
dimension "box"
|
||||
}
|
||||
|
||||
ktest1 {
|
||||
dimension "box"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
task jarTestFolders() {
|
||||
@@ -81,7 +92,8 @@ tasks.withType(JavaCompile) {
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
androidTestImplementation 'junit:junit:4.12'
|
||||
implementation 'com.android.support:multidex:1.0.3'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation fileTree(dir: 'libs/test', include: ['*.jar'])
|
||||
|
||||
ktest0Implementation fileTree(dir: 'libs/test', include: ['libtest0.jar'])
|
||||
ktest1Implementation fileTree(dir: 'libs/test', include: ['libtest1.jar'])
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system edit
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
#
|
||||
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||
#proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt
|
||||
|
||||
# Project target.
|
||||
target=android-16
|
||||
@@ -53,3 +53,7 @@ projectTest {
|
||||
|
||||
workingDir = rootDir
|
||||
}
|
||||
|
||||
val generateTests by generator("org.jetbrains.kotlin.android.tests.CodegenTestsOnAndroidGenerator")
|
||||
|
||||
generateTests.workingDir = rootDir
|
||||
|
||||
+16
-11
@@ -30,6 +30,7 @@ import java.io.File
|
||||
import java.io.IOException
|
||||
import javax.xml.parsers.DocumentBuilderFactory
|
||||
import javax.xml.parsers.ParserConfigurationException
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class CodegenTestsOnAndroidRunner private constructor(private val pathManager: PathManager) {
|
||||
|
||||
@@ -59,7 +60,7 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
|
||||
rootSuite.addTest(this)
|
||||
}
|
||||
|
||||
renameReport()
|
||||
renameFlavorFolder()
|
||||
enableD8(true)
|
||||
runTestsOnEmulator(gradleRunner, TestSuite("D8")).apply {
|
||||
(0 until this.countTestCases()).forEach {
|
||||
@@ -95,22 +96,27 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
|
||||
}
|
||||
|
||||
private fun processReport(suite: TestSuite, resultOutput: String) {
|
||||
val reportFolder = reportFolder()
|
||||
val reportFolder = File(flavorFolder())
|
||||
try {
|
||||
val testCases = parseSingleReportInFolder(reportFolder)
|
||||
testCases.forEach { aCase -> suite.addTest(aCase) }
|
||||
Assert.assertNotEquals("There is no test results in report", 0, testCases.size.toLong())
|
||||
val folders = reportFolder.listFiles()
|
||||
assertTrue(folders != null && folders.isNotEmpty(), "No folders in ${reportFolder.path}")
|
||||
folders.forEach {
|
||||
assertTrue("${it.path} is not directory") { it.isDirectory }
|
||||
val testCases = parseSingleReportInFolder(it)
|
||||
testCases.forEach { aCase -> suite.addTest(aCase) }
|
||||
Assert.assertNotEquals("There is no test results in report", 0, testCases.size.toLong())
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
throw RuntimeException("Can't parse test results in $reportFolder\n$resultOutput", e)
|
||||
}
|
||||
}
|
||||
|
||||
private fun renameReport() {
|
||||
val reportFolder = File(reportFolder())
|
||||
private fun renameFlavorFolder() {
|
||||
val reportFolder = File(flavorFolder())
|
||||
reportFolder.renameTo(File(reportFolder.parentFile, reportFolder.name + "_dex"))
|
||||
}
|
||||
|
||||
private fun reportFolder() = pathManager.tmpFolder + "/build/test/results/connected/"
|
||||
private fun flavorFolder() = pathManager.tmpFolder + "/build/test/results/connected/flavors"
|
||||
|
||||
private fun runTestsOnEmulator(gradleRunner: GradleRunner, suite: TestSuite): TestSuite {
|
||||
val platformPrefixProperty = System.setProperty(PlatformUtils.PLATFORM_PREFIX_KEY, "Idea")
|
||||
@@ -153,11 +159,10 @@ class CodegenTestsOnAndroidRunner private constructor(private val pathManager: P
|
||||
}
|
||||
|
||||
@Throws(IOException::class, SAXException::class, ParserConfigurationException::class)
|
||||
private fun parseSingleReportInFolder(reportFolder: String): List<TestCase> {
|
||||
val folder = File(reportFolder)
|
||||
private fun parseSingleReportInFolder(folder: File): List<TestCase> {
|
||||
val files = folder.listFiles()!!
|
||||
assert(files.size == 1) {
|
||||
"Expecting one file but ${files.size}: ${files.joinToString { it.name }}"
|
||||
"Expecting one file but ${files.size}: ${files.joinToString { it.name }} in ${folder.path}"
|
||||
}
|
||||
val reportFile = files[0]
|
||||
|
||||
|
||||
@@ -60,10 +60,6 @@ public class PathManager {
|
||||
return tmpFolder + "/libs/libtest" + index;
|
||||
}
|
||||
|
||||
public String getLibsFolderInAndroidTestedModuleTmpFolder() {
|
||||
return tmpFolder + "/tested-module/libs";
|
||||
}
|
||||
|
||||
public String getLibsFolderInAndroidTmpFolder() {
|
||||
return tmpFolder + "/libs";
|
||||
}
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ public class SDKDownloader {
|
||||
private static final String SDK_TOOLS = "4333796"; //"26.1.1";
|
||||
public static final String BUILD_TOOLS = "28.0.3";
|
||||
private static final int ANDROID_VERSION = 19;
|
||||
public static final String GRADLE_VERSION = "4.6";
|
||||
public static final String GRADLE_VERSION = "5.1.1";
|
||||
public static final String EMULATOR_TOOLS_VERSION = "5264690"; //"28.0.23";
|
||||
|
||||
|
||||
|
||||
+1
-2
@@ -70,8 +70,7 @@ public class GradleRunner {
|
||||
System.out.println("Starting tests...");
|
||||
GeneralCommandLine test = generateCommandLine("connectedAndroidTest");
|
||||
test.addParameters("--stacktrace");
|
||||
//To avoid problem with discovering tests on Android in multidex build
|
||||
test.addParameters("-Pandroid.testInstrumentationRunnerArguments.class=org.jetbrains.kotlin.android.tests.CodegenTestCaseOnAndroid");
|
||||
test.addParameters("--continue"); //run all flavors even if any fail
|
||||
return RunUtils.execute(test).getOutput();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,14 +19,11 @@ package org.jetbrains.kotlin.android.tests;
|
||||
import com.google.common.io.Files;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import junit.framework.TestSuite;
|
||||
import kotlin.io.FilesKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.AllTests;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
@RunWith(AllTests.class)
|
||||
public class AndroidRunner {
|
||||
@@ -47,9 +44,6 @@ public class AndroidRunner {
|
||||
public static TestSuite suite() throws Throwable {
|
||||
PathManager pathManager = getPathManager();
|
||||
|
||||
FileUtil.copyDir(new File(pathManager.getAndroidModuleRoot()), new File(pathManager.getTmpFolder()));
|
||||
writeAndroidSkdToLocalProperties();
|
||||
|
||||
CodegenTestsOnAndroidGenerator.generate(pathManager);
|
||||
|
||||
System.out.println("Run tests on android...");
|
||||
@@ -65,12 +59,4 @@ public class AndroidRunner {
|
||||
FileUtil.delete(new File(pathManager.getTmpFolder()));
|
||||
}
|
||||
|
||||
private static void writeAndroidSkdToLocalProperties() throws IOException {
|
||||
String sdkRoot = FilesKt.getInvariantSeparatorsPath(new File(pathManager.getAndroidSdkRoot()));
|
||||
System.out.println("Writing android sdk to local.properties: " + sdkRoot);
|
||||
File file = new File(pathManager.getTmpFolder() + "/local.properties");
|
||||
try (FileWriter fw = new FileWriter(file)) {
|
||||
fw.write("sdk.dir=" + sdkRoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -32,7 +32,7 @@ private val importPattern = Pattern.compile("import[ |\t]([\\w|]*\\.)")
|
||||
|
||||
private data class OldPackageAndNew(val oldFqName: FqName, val newFqName: FqName)
|
||||
|
||||
internal fun patchFiles(
|
||||
internal fun patchFilesAndAddTest(
|
||||
testFile: File,
|
||||
testFiles: List<CodegenTestCase.TestFile>,
|
||||
filesHolder: CodegenTestsOnAndroidGenerator.FilesWriter
|
||||
@@ -103,16 +103,16 @@ internal fun patchFiles(
|
||||
file.content = file.content.patchSelfImports(file.newPackage)
|
||||
}
|
||||
|
||||
resultFiles.forEach { resultFile ->
|
||||
if (resultFile.name.endsWith(".kt") || resultFile.name.endsWith(".kts")) {
|
||||
filesHolder.addFile(resultFile.name, resultFile.content)
|
||||
}
|
||||
}
|
||||
|
||||
val boxFiles = resultFiles.filter { hasBoxMethod(it.content) }
|
||||
if (boxFiles.size != 1) {
|
||||
println("Several box methods in $testFile")
|
||||
}
|
||||
|
||||
filesHolder.addTest(
|
||||
resultFiles.filter { resultFile -> resultFile.name.endsWith(".kt") || resultFile.name.endsWith(".kts") },
|
||||
TestInfo("", boxFiles.last().newClassId, testFile)
|
||||
)
|
||||
|
||||
return boxFiles.last().newClassId
|
||||
}
|
||||
|
||||
|
||||
+74
-93
@@ -5,11 +5,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.android.tests
|
||||
|
||||
import com.google.common.collect.Lists
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.jetbrains.kotlin.cli.common.output.writeAllTo
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||
@@ -20,16 +18,13 @@ import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.*
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.junit.Assert
|
||||
import org.junit.Ignore
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
data class ConfigurationKey(val kind: ConfigurationKind, val jdkKind: TestJdkKind, val configuration: String)
|
||||
|
||||
@@ -39,24 +34,31 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
|
||||
private var currentModuleIndex = 1
|
||||
|
||||
private val generatedTestNames = Lists.newArrayList<String>()
|
||||
|
||||
private val pathFilter: String? = System.getProperties().getProperty("kotlin.test.android.path.filter")
|
||||
|
||||
private fun generateOutputFiles() {
|
||||
private val pendingUnitTestGenerators = hashMapOf<Int, UnitTestFileWriter>()
|
||||
|
||||
//keep it globally to avoid test grouping on TC
|
||||
private val generatedTestNames = hashSetOf<String>()
|
||||
|
||||
fun getFlavorUnitTestFilePath(index: Int): String {
|
||||
return pathManager.srcFolderInAndroidTmpFolder + "/androidTestKtest$index/java/" + testClassPackage.replace(
|
||||
".",
|
||||
"/"
|
||||
) + "/" + testClassName + "$index.java"
|
||||
}
|
||||
|
||||
private fun prepareAndroidModuleAndGenerateTests() {
|
||||
prepareAndroidModule()
|
||||
generateAndSave()
|
||||
generateTestsAndFlavourSuites()
|
||||
}
|
||||
|
||||
private fun prepareAndroidModule() {
|
||||
FileUtil.copyDir(File(pathManager.androidModuleRoot), File(pathManager.tmpFolder))
|
||||
writeAndroidSkdToLocalProperties(pathManager)
|
||||
|
||||
println("Copying kotlin-stdlib.jar and kotlin-reflect.jar in android module...")
|
||||
copyKotlinRuntimeJars()
|
||||
|
||||
println("Check 'libs' folder in tested android module...")
|
||||
val libsFolderInTestedModule = File(pathManager.libsFolderInAndroidTestedModuleTmpFolder)
|
||||
if (!libsFolderInTestedModule.exists()) {
|
||||
libsFolderInTestedModule.mkdirs()
|
||||
}
|
||||
}
|
||||
|
||||
private fun copyKotlinRuntimeJars() {
|
||||
@@ -75,38 +77,20 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
)
|
||||
}
|
||||
|
||||
private fun generateAndSave() {
|
||||
private fun generateTestsAndFlavourSuites() {
|
||||
println("Generating test files...")
|
||||
val testSourceFilePath =
|
||||
pathManager.srcFolderInAndroidTmpFolder + "/androidTest/java/" + testClassPackage.replace(".", "/") + "/" + testClassName + ".java"
|
||||
|
||||
FileWriter(File(testSourceFilePath).also { it.parentFile.mkdirs() }).use {
|
||||
val p = Printer(it)
|
||||
p.println(
|
||||
"""package $testClassPackage;
|
||||
|
|
||||
|import $baseTestClassPackage.$baseTestClassName;
|
||||
|
|
||||
|/* This class is generated by $generatorName. DO NOT MODIFY MANUALLY */
|
||||
|public class $testClassName extends $baseTestClassName {
|
||||
|
|
||||
""".trimMargin()
|
||||
)
|
||||
p.pushIndent()
|
||||
generateTestMethodsForDirectories(File("compiler/testData/codegen/box"), File("compiler/testData/codegen/boxInline"))
|
||||
|
||||
generateTestMethodsForDirectories(p, File("compiler/testData/codegen/box"), File("compiler/testData/codegen/boxInline"))
|
||||
|
||||
p.popIndent()
|
||||
p.println("}")
|
||||
}
|
||||
pendingUnitTestGenerators.values.forEach { it.generate() }
|
||||
}
|
||||
|
||||
private fun generateTestMethodsForDirectories(p: Printer, vararg dirs: File) {
|
||||
private fun generateTestMethodsForDirectories(vararg dirs: File) {
|
||||
val holders = mutableMapOf<ConfigurationKey, FilesWriter>()
|
||||
|
||||
for (dir in dirs) {
|
||||
val files = dir.listFiles() ?: error("Folder with testData is empty: ${dir.absolutePath}")
|
||||
processFiles(p, files, holders)
|
||||
processFiles(files, holders)
|
||||
}
|
||||
|
||||
holders.values.forEach {
|
||||
@@ -117,7 +101,8 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
internal inner class FilesWriter(
|
||||
private val configuration: CompilerConfiguration
|
||||
) {
|
||||
private val rawFiles: MutableList<Pair<String, String>> = ArrayList()
|
||||
private val rawFiles = arrayListOf<TestClassInfo>()
|
||||
private val unitTestDescriptions = arrayListOf<TestInfo>()
|
||||
|
||||
private fun shouldWriteFilesOnDisk(): Boolean = rawFiles.size > 300
|
||||
|
||||
@@ -139,27 +124,26 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
writeFiles(
|
||||
rawFiles.map {
|
||||
try {
|
||||
CodegenTestFiles.create(it.first, it.second, environment.project).psiFile
|
||||
CodegenTestFiles.create(it.name, it.content, environment.project).psiFile
|
||||
} catch (e: Throwable) {
|
||||
throw RuntimeException("Error on processing ${it.first}:\n${it.second}", e)
|
||||
throw RuntimeException("Error on processing ${it.name}:\n${it.content}", e)
|
||||
}
|
||||
}, environment
|
||||
)
|
||||
Disposer.dispose(disposable)
|
||||
rawFiles.clear()
|
||||
}
|
||||
|
||||
fun addFile(name: String, content: String) {
|
||||
rawFiles.add(name to content)
|
||||
unitTestDescriptions.clear()
|
||||
}
|
||||
|
||||
private fun writeFiles(filesToCompile: List<KtFile>, environment: KotlinCoreEnvironment) {
|
||||
if (filesToCompile.isEmpty()) return
|
||||
|
||||
//1000 files per folder, each folder would be jared by build.gradle script
|
||||
// We can't create one big jar with all test cause dex has problem with memory on teamcity
|
||||
//3000 files per folder that would be used by flavor to avoid multidex usage,
|
||||
// each folder would be jared by build.gradle script
|
||||
writtenFilesCount += filesToCompile.size
|
||||
val outputDir = File(pathManager.getOutputForCompiledFiles(writtenFilesCount / 1000))
|
||||
val index = writtenFilesCount / 3000
|
||||
val outputDir = File(pathManager.getOutputForCompiledFiles(index))
|
||||
assertTrue("Add flavors for ktest$index", index < 2)
|
||||
|
||||
println("Generating ${filesToCompile.size} files into ${outputDir.name}, configuration: '${environment.configuration}'...")
|
||||
|
||||
@@ -169,14 +153,25 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
outputDir.mkdirs()
|
||||
}
|
||||
Assert.assertTrue("Cannot create directory for compiled files", outputDir.exists())
|
||||
|
||||
val unitTestFileWriter = pendingUnitTestGenerators.getOrPut(index) {
|
||||
UnitTestFileWriter(
|
||||
getFlavorUnitTestFilePath(index),
|
||||
index,
|
||||
generatedTestNames
|
||||
)
|
||||
}
|
||||
unitTestFileWriter.addTests(unitTestDescriptions)
|
||||
outputFiles.writeAllTo(outputDir)
|
||||
}
|
||||
|
||||
fun addTest(testFiles: List<TestClassInfo>, info: TestInfo) {
|
||||
rawFiles.addAll(testFiles)
|
||||
unitTestDescriptions.add(info)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
private fun processFiles(
|
||||
printer: Printer,
|
||||
files: Array<File>,
|
||||
holders: MutableMap<ConfigurationKey, FilesWriter>
|
||||
) {
|
||||
@@ -191,7 +186,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
if (file.isDirectory) {
|
||||
val listFiles = file.listFiles()
|
||||
if (listFiles != null) {
|
||||
processFiles(printer, listFiles, holders)
|
||||
processFiles(listFiles, holders)
|
||||
}
|
||||
} else if (FileUtilRt.getExtension(file.name) != KotlinFileType.EXTENSION) {
|
||||
// skip non kotlin files
|
||||
@@ -204,9 +199,8 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
continue
|
||||
}
|
||||
|
||||
val fullFileText = FileUtil.loadFile(file, true).let {
|
||||
it.replace("COROUTINES_PACKAGE", "kotlin.coroutines")
|
||||
}
|
||||
val fullFileText =
|
||||
FileUtil.loadFile(file, true).replace("COROUTINES_PACKAGE", "kotlin.coroutines")
|
||||
|
||||
if (fullFileText.contains("// WITH_COROUTINES")) {
|
||||
if (fullFileText.contains("kotlin.coroutines.experimental")) continue
|
||||
@@ -237,70 +231,57 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
|
||||
})
|
||||
}
|
||||
|
||||
val classWithBoxMethod = patchFiles(file, testFiles, filesHolder) ?: continue
|
||||
|
||||
val generatedTestName = generateTestName(file.name)
|
||||
generateTestMethod(
|
||||
printer,
|
||||
generatedTestName,
|
||||
classWithBoxMethod.asString(),
|
||||
StringUtil.escapeStringCharacters(file.path)
|
||||
)
|
||||
patchFilesAndAddTest(file, testFiles, filesHolder)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createTestFiles(file: File, expectedText: String): List<CodegenTestCase.TestFile> =
|
||||
private fun createTestFiles(file: File, expectedText: String): List<TestFile> =
|
||||
KotlinTestUtils.createTestFiles(
|
||||
file.name,
|
||||
expectedText,
|
||||
object : KotlinTestUtils.TestFileFactoryNoModules<CodegenTestCase.TestFile>() {
|
||||
override fun create(fileName: String, text: String, directives: Map<String, String>): CodegenTestCase.TestFile {
|
||||
return CodegenTestCase.TestFile(fileName, text)
|
||||
object : KotlinTestUtils.TestFileFactoryNoModules<TestFile>() {
|
||||
override fun create(fileName: String, text: String, directives: Map<String, String>): TestFile {
|
||||
return TestFile(fileName, text)
|
||||
}
|
||||
}, false,
|
||||
"kotlin.coroutines"
|
||||
)
|
||||
|
||||
|
||||
private fun generateTestName(fileName: String): String {
|
||||
var result = NameUtils.sanitizeAsJavaIdentifier(FileUtil.getNameWithoutExtension(StringUtil.capitalize(fileName)))
|
||||
|
||||
var i = 0
|
||||
while (generatedTestNames.contains(result)) {
|
||||
result += "_" + i++
|
||||
}
|
||||
generatedTestNames.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val testClassPackage = "org.jetbrains.kotlin.android.tests"
|
||||
private const val testClassName = "CodegenTestCaseOnAndroid"
|
||||
private const val baseTestClassPackage = "org.jetbrains.kotlin.android.tests"
|
||||
private const val baseTestClassName = "AbstractCodegenTestCaseOnAndroid"
|
||||
private const val generatorName = "CodegenTestsOnAndroidGenerator"
|
||||
const val testClassPackage = "org.jetbrains.kotlin.android.tests"
|
||||
const val testClassName = "CodegenTestCaseOnAndroid"
|
||||
const val baseTestClassPackage = "org.jetbrains.kotlin.android.tests"
|
||||
const val baseTestClassName = "AbstractCodegenTestCaseOnAndroid"
|
||||
const val generatorName = "CodegenTestsOnAndroidGenerator"
|
||||
|
||||
|
||||
@JvmStatic
|
||||
@Throws(Throwable::class)
|
||||
fun generate(pathManager: PathManager) {
|
||||
CodegenTestsOnAndroidGenerator(pathManager).generateOutputFiles()
|
||||
CodegenTestsOnAndroidGenerator(pathManager).prepareAndroidModuleAndGenerateTests()
|
||||
}
|
||||
|
||||
|
||||
private fun hasBoxMethod(text: String): Boolean {
|
||||
return text.contains("fun box()")
|
||||
}
|
||||
|
||||
private fun generateTestMethod(p: Printer, testName: String, className: String, filePath: String) {
|
||||
p.println("public void test$testName() throws Exception {")
|
||||
p.pushIndent()
|
||||
p.println("invokeBoxMethod($className.class, \"$filePath\", \"OK\");")
|
||||
p.popIndent()
|
||||
p.println("}")
|
||||
p.println()
|
||||
@Throws(IOException::class)
|
||||
internal fun writeAndroidSkdToLocalProperties(pathManager: PathManager) {
|
||||
val sdkRoot = File(pathManager.androidSdkRoot).invariantSeparatorsPath
|
||||
println("Writing android sdk to local.properties: $sdkRoot")
|
||||
val file = File(pathManager.tmpFolder + "/local.properties")
|
||||
FileWriter(file).use { fw -> fw.write("sdk.dir=$sdkRoot") }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
val tmpFolder = createTempDir()
|
||||
println("Created temporary folder for android tests: " + tmpFolder.absolutePath)
|
||||
val rootFolder = File("")
|
||||
val pathManager = PathManager(rootFolder.absolutePath, tmpFolder.absolutePath)
|
||||
generate(pathManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.android.tests
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
|
||||
class TestInfo(val name: String, val fqName: FqName, val file: File)
|
||||
|
||||
class UnitTestFileWriter(private val fileName: String, private val index: Int, private val generatedTestNames: MutableSet<String>) {
|
||||
private val infos = arrayListOf<TestInfo>()
|
||||
|
||||
fun addTests(info: List<TestInfo>) {
|
||||
infos.addAll(info)
|
||||
}
|
||||
|
||||
fun generate() {
|
||||
FileWriter(File(fileName).also { it.parentFile.mkdirs() }).use { suite ->
|
||||
val p = Printer(suite)
|
||||
p.println(
|
||||
"""package ${CodegenTestsOnAndroidGenerator.testClassPackage};
|
||||
|
|
||||
|import ${CodegenTestsOnAndroidGenerator.baseTestClassPackage}.${CodegenTestsOnAndroidGenerator.baseTestClassName};
|
||||
|
|
||||
|/* This class is generated by ${CodegenTestsOnAndroidGenerator.generatorName}. DO NOT MODIFY MANUALLY */
|
||||
|public class ${CodegenTestsOnAndroidGenerator.testClassName}$index extends ${CodegenTestsOnAndroidGenerator.baseTestClassName} {
|
||||
|
|
||||
""".trimMargin()
|
||||
)
|
||||
p.pushIndent()
|
||||
|
||||
infos.forEach { info ->
|
||||
generateTestMethod(
|
||||
p,
|
||||
generateTestName(info.file.name),
|
||||
info.fqName.asString(),
|
||||
StringUtil.escapeStringCharacters(info.file.path)
|
||||
)
|
||||
}
|
||||
|
||||
p.popIndent()
|
||||
p.println("}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateTestName(fileName: String): String {
|
||||
var result = NameUtils.sanitizeAsJavaIdentifier(FileUtil.getNameWithoutExtension(StringUtil.capitalize(fileName)))
|
||||
|
||||
var i = 0
|
||||
while (generatedTestNames.contains(result)) {
|
||||
result += "_" + i++
|
||||
}
|
||||
generatedTestNames.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun generateTestMethod(p: Printer, testName: String, className: String, filePath: String) {
|
||||
p.println("public void test$testName() throws Exception {")
|
||||
p.pushIndent()
|
||||
p.println("invokeBoxMethod($className.class, \"$filePath\", \"OK\");")
|
||||
p.popIndent()
|
||||
p.println("}")
|
||||
p.println()
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user