[TEST] Invert dependency between :test-generator and :tests-common modules
This is needed to provide ability for declaring new implementations of test generators, based on existing infrastructure, which won't add dependency on :compiler:tests-common Also this commit removes implicit dependency on :compiler:tests-common from :compiler:tests-common-new
This commit is contained in:
@@ -45,6 +45,8 @@ dependencies {
|
||||
testCompile(project(":js:js.translator"))
|
||||
testCompile(project(":native:frontend.native"))
|
||||
testCompileOnly(project(":plugins:android-extensions-compiler"))
|
||||
testApi(projectTests(":generators:test-generator"))
|
||||
testCompile(projectTests(":compiler:tests-classic-compiler-utils"))
|
||||
testCompile(project(":kotlin-test:kotlin-test-jvm"))
|
||||
testCompile(projectTests(":compiler:tests-common-jvm6"))
|
||||
testCompile(project(":kotlin-scripting-compiler-impl"))
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.generators.impl
|
||||
|
||||
import org.jetbrains.kotlin.generators.model.MethodModel
|
||||
import org.jetbrains.kotlin.generators.MethodGenerator
|
||||
import org.jetbrains.kotlin.generators.model.RunTestMethodModel
|
||||
import org.jetbrains.kotlin.test.TargetBackend
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
|
||||
object RunTestMethodGenerator : MethodGenerator<RunTestMethodModel>() {
|
||||
override val kind: MethodModel.Kind
|
||||
get() = RunTestMethodModel.Kind
|
||||
|
||||
override fun generateBody(method: RunTestMethodModel, p: Printer) {
|
||||
with(method) {
|
||||
if (!isWithTargetBackend()) {
|
||||
p.println("KotlinTestUtils.${method.testRunnerMethodName}(this::$testMethodName, this, testDataFilePath);")
|
||||
} else {
|
||||
val className = TargetBackend::class.java.simpleName
|
||||
val additionalArguments = if (additionalRunnerArguments.isNotEmpty())
|
||||
additionalRunnerArguments.joinToString(separator = ", ", prefix = ", ")
|
||||
else ""
|
||||
p.println("KotlinTestUtils.$testRunnerMethodName(this::$testMethodName, $className.$targetBackend, testDataFilePath$additionalArguments);")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun generateSignature(method: RunTestMethodModel, p: Printer) {
|
||||
p.print("private void ${method.name}(String testDataFilePath) throws Exception")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.generators.impl
|
||||
|
||||
import org.jetbrains.kotlin.generators.InconsistencyChecker
|
||||
import org.jetbrains.kotlin.generators.InconsistencyChecker.Companion.inconsistencyChecker
|
||||
import org.jetbrains.kotlin.generators.TestGroupSuite
|
||||
import org.jetbrains.kotlin.generators.testGroupSuite
|
||||
|
||||
fun generateTestGroupSuite(
|
||||
args: Array<String>,
|
||||
init: TestGroupSuite.() -> Unit
|
||||
) {
|
||||
generateTestGroupSuite(InconsistencyChecker.hasDryRunArg(args), init)
|
||||
}
|
||||
|
||||
fun generateTestGroupSuite(
|
||||
dryRun: Boolean = false,
|
||||
init: TestGroupSuite.() -> Unit
|
||||
) {
|
||||
val suite = testGroupSuite(init)
|
||||
for (testGroup in suite.testGroups) {
|
||||
for (testClass in testGroup.testClasses) {
|
||||
val (changed, testSourceFilePath) = TestGeneratorImpl.generateAndSave(testClass, dryRun)
|
||||
if (changed) {
|
||||
inconsistencyChecker(dryRun).add(testSourceFilePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.generators.impl
|
||||
|
||||
import org.jetbrains.kotlin.generators.MethodGenerator
|
||||
import org.jetbrains.kotlin.generators.TestGenerator
|
||||
import org.jetbrains.kotlin.generators.TestGroup
|
||||
import org.jetbrains.kotlin.generators.model.*
|
||||
import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import org.jetbrains.kotlin.test.TestMetadata
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil
|
||||
import org.jetbrains.kotlin.utils.Printer
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.BlockJUnit4ClassRunner
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
private val METHOD_GENERATORS = listOf(
|
||||
RunTestMethodGenerator,
|
||||
SimpleTestClassModelTestAllFilesPresentMethodGenerator,
|
||||
SimpleTestMethodGenerator,
|
||||
SingleClassTestModelAllFilesPresentedMethodGenerator
|
||||
)
|
||||
|
||||
object TestGeneratorImpl : TestGenerator(METHOD_GENERATORS) {
|
||||
override fun generateAndSave(testClass: TestGroup.TestClass, dryRun: Boolean): GenerationResult {
|
||||
val generatorInstance = TestGeneratorImplInstance(
|
||||
testClass.baseDir,
|
||||
testClass.suiteTestClassName,
|
||||
testClass.baseTestClassName,
|
||||
testClass.testModels,
|
||||
testClass.useJunit4,
|
||||
methodGenerators
|
||||
)
|
||||
return generatorInstance.generateAndSave(dryRun)
|
||||
}
|
||||
}
|
||||
|
||||
private class TestGeneratorImplInstance(
|
||||
baseDir: String,
|
||||
suiteTestClassFqName: String,
|
||||
baseTestClassFqName: String,
|
||||
private val testClassModels: Collection<TestClassModel>,
|
||||
private val useJunit4: Boolean,
|
||||
private val methodGenerators: Map<MethodModel.Kind, MethodGenerator<*>>
|
||||
) {
|
||||
companion object {
|
||||
private val GENERATED_FILES = HashSet<String>()
|
||||
private val RUNNER = JUnit3RunnerWithInners::class.java
|
||||
private val JUNIT4_RUNNER = BlockJUnit4ClassRunner::class.java
|
||||
|
||||
private fun generateMetadata(p: Printer, testDataSource: TestEntityModel) {
|
||||
val dataString = testDataSource.dataString
|
||||
if (dataString != null) {
|
||||
p.println("@TestMetadata(\"", dataString, "\")")
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateTestDataPath(p: Printer, testClassModel: TestClassModel) {
|
||||
val dataPathRoot = testClassModel.dataPathRoot
|
||||
if (dataPathRoot != null) {
|
||||
p.println("@TestDataPath(\"", dataPathRoot, "\")")
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateParameterAnnotations(p: Printer, testClassModel: TestClassModel) {
|
||||
for (annotationModel in testClassModel.annotations) {
|
||||
annotationModel.generate(p)
|
||||
p.println()
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateSuppressAllWarnings(p: Printer) {
|
||||
p.println("@SuppressWarnings(\"all\")")
|
||||
}
|
||||
}
|
||||
|
||||
private val baseTestClassPackage: String = baseTestClassFqName.substringBeforeLast('.', "")
|
||||
private val baseTestClassName: String = baseTestClassFqName.substringAfterLast('.', baseTestClassFqName)
|
||||
private val suiteClassPackage: String = suiteTestClassFqName.substringBeforeLast('.', baseTestClassPackage)
|
||||
private val suiteClassName: String = suiteTestClassFqName.substringAfterLast('.', suiteTestClassFqName)
|
||||
private val testSourceFilePath: String = baseDir + "/" + this.suiteClassPackage.replace(".", "/") + "/" + this.suiteClassName + ".java"
|
||||
|
||||
init {
|
||||
if (!GENERATED_FILES.add(testSourceFilePath)) {
|
||||
throw IllegalArgumentException("Same test file already generated in current session: $testSourceFilePath")
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(IOException::class)
|
||||
fun generateAndSave(dryRun: Boolean): TestGenerator.GenerationResult {
|
||||
val generatedCode = generate()
|
||||
|
||||
val testSourceFile = File(testSourceFilePath)
|
||||
val changed =
|
||||
GeneratorsFileUtil.isFileContentChangedIgnoringLineSeparators(testSourceFile, generatedCode)
|
||||
if (!dryRun) {
|
||||
GeneratorsFileUtil.writeFileIfContentChanged(testSourceFile, generatedCode, false)
|
||||
}
|
||||
return TestGenerator.GenerationResult(changed, testSourceFilePath)
|
||||
}
|
||||
|
||||
private fun generate(): String {
|
||||
val out = StringBuilder()
|
||||
val p = Printer(out)
|
||||
|
||||
val year = GregorianCalendar()[Calendar.YEAR]
|
||||
p.println(
|
||||
"""/*
|
||||
| * Copyright 2010-$year 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.
|
||||
| */
|
||||
|""".trimMargin()
|
||||
)
|
||||
p.println("package ", suiteClassPackage, ";")
|
||||
p.println()
|
||||
p.println("import com.intellij.testFramework.TestDataPath;")
|
||||
if (!useJunit4) {
|
||||
p.println("import ", RUNNER.canonicalName, ";")
|
||||
}
|
||||
p.println("import " + KotlinTestUtils::class.java.canonicalName + ";")
|
||||
p.println("import " + KtTestUtil::class.java.canonicalName + ";")
|
||||
|
||||
for (clazz in testClassModels.flatMapTo(mutableSetOf()) { classModel -> classModel.imports }) {
|
||||
p.println("import ${clazz.name};")
|
||||
}
|
||||
|
||||
if (suiteClassPackage != baseTestClassPackage) {
|
||||
p.println("import $baseTestClassPackage.$baseTestClassName;")
|
||||
}
|
||||
|
||||
p.println("import " + TestMetadata::class.java.canonicalName + ";")
|
||||
p.println("import " + RunWith::class.java.canonicalName + ";")
|
||||
if (useJunit4) {
|
||||
p.println("import " + BlockJUnit4ClassRunner::class.java.canonicalName + ";")
|
||||
p.println("import " + Test::class.java.canonicalName + ";")
|
||||
}
|
||||
p.println()
|
||||
p.println("import java.io.File;")
|
||||
p.println("import java.util.regex.Pattern;")
|
||||
p.println()
|
||||
p.println("/** This class is generated by {@link ", KotlinTestUtils.TEST_GENERATOR_NAME, "}. DO NOT MODIFY MANUALLY */")
|
||||
|
||||
generateSuppressAllWarnings(p)
|
||||
|
||||
val model: TestClassModel
|
||||
if (testClassModels.size == 1) {
|
||||
model = object : DelegatingTestClassModel(testClassModels.single()) {
|
||||
override val name: String
|
||||
get() = suiteClassName
|
||||
}
|
||||
} else {
|
||||
model = object : TestClassModel() {
|
||||
override val innerTestClasses: Collection<TestClassModel>
|
||||
get() = testClassModels
|
||||
|
||||
override val methods: Collection<MethodModel>
|
||||
get() = emptyList()
|
||||
|
||||
override val isEmpty: Boolean
|
||||
get() = false
|
||||
|
||||
override val name: String
|
||||
get() = suiteClassName
|
||||
|
||||
override val dataString: String?
|
||||
get() = null
|
||||
|
||||
override val dataPathRoot: String?
|
||||
get() = null
|
||||
|
||||
override val annotations: Collection<AnnotationModel>
|
||||
get() = emptyList()
|
||||
|
||||
override val imports: Set<Class<*>>
|
||||
get() = super.imports
|
||||
}
|
||||
}
|
||||
|
||||
generateTestClass(p, model, false)
|
||||
return out.toString()
|
||||
}
|
||||
|
||||
private fun generateTestClass(p: Printer, testClassModel: TestClassModel, isStatic: Boolean) {
|
||||
val staticModifier = if (isStatic) "static " else ""
|
||||
|
||||
generateMetadata(p, testClassModel)
|
||||
generateTestDataPath(p, testClassModel)
|
||||
generateParameterAnnotations(p, testClassModel)
|
||||
|
||||
p.println("@RunWith(", if (useJunit4) JUNIT4_RUNNER.simpleName else RUNNER.simpleName, ".class)")
|
||||
|
||||
p.println("public " + staticModifier + "class ", testClassModel.name, " extends ", baseTestClassName, " {")
|
||||
p.pushIndent()
|
||||
|
||||
val testMethods = testClassModel.methods
|
||||
val innerTestClasses = testClassModel.innerTestClasses
|
||||
|
||||
var first = true
|
||||
|
||||
for (methodModel in testMethods) {
|
||||
if (!methodModel.shouldBeGenerated()) continue
|
||||
|
||||
if (first) {
|
||||
first = false
|
||||
} else {
|
||||
p.println()
|
||||
}
|
||||
|
||||
generateTestMethod(p, methodModel, useJunit4)
|
||||
}
|
||||
|
||||
for (innerTestClass in innerTestClasses) {
|
||||
if (!innerTestClass.isEmpty) {
|
||||
if (first) {
|
||||
first = false
|
||||
} else {
|
||||
p.println()
|
||||
}
|
||||
|
||||
generateTestClass(p, innerTestClass, true)
|
||||
}
|
||||
}
|
||||
|
||||
p.popIndent()
|
||||
p.println("}")
|
||||
}
|
||||
|
||||
private fun generateTestMethod(p: Printer, methodModel: MethodModel, useJunit4: Boolean) {
|
||||
if (useJunit4 && (methodModel !is RunTestMethodModel)) {
|
||||
p.println("@Test")
|
||||
}
|
||||
|
||||
val generator = methodGenerators.getValue(methodModel.kind)
|
||||
|
||||
generateMetadata(p, methodModel)
|
||||
generator.hackyGenerateSignature(methodModel, p)
|
||||
p.printWithNoIndent(" {")
|
||||
p.println()
|
||||
|
||||
p.pushIndent()
|
||||
|
||||
generator.hackyGenerateBody(methodModel, p)
|
||||
|
||||
p.popIndent()
|
||||
p.println("}")
|
||||
}
|
||||
|
||||
private fun <T : MethodModel> MethodGenerator<T>.hackyGenerateBody(method: MethodModel, p: Printer) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
generateBody(method as T, p)
|
||||
}
|
||||
|
||||
private fun <T : MethodModel> MethodGenerator<T>.hackyGenerateSignature(method: MethodModel, p: Printer) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
generateSignature(method as T, p)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2018 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.test
|
||||
|
||||
enum class ConfigurationKind(
|
||||
val withRuntime: Boolean = false,
|
||||
val withMockRuntime: Boolean = false,
|
||||
val withReflection: Boolean = false
|
||||
) {
|
||||
/** JDK without any kotlin runtime */
|
||||
JDK_NO_RUNTIME(),
|
||||
/** JDK + light mock kotlin runtime */
|
||||
JDK_ONLY(withMockRuntime = true),
|
||||
/** JDK + kotlin runtime but without reflection */
|
||||
NO_KOTLIN_REFLECT(withRuntime = true),
|
||||
/** JDK + kotlin runtime + kotlin reflection */
|
||||
ALL(withRuntime = true, withReflection = true)
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.test;
|
||||
|
||||
public enum TestJdkKind {
|
||||
MOCK_JDK,
|
||||
// Differs from common mock JDK only by one additional 'nonExistingMethod' in Collection and constructor from Double in Throwable
|
||||
// It's needed to test the way we load additional built-ins members that neither in black nor white lists
|
||||
// Also, now it contains new methods in java.lang.String introduced in JDK 11
|
||||
MODIFIED_MOCK_JDK,
|
||||
// JDK found at $JDK_16
|
||||
FULL_JDK_6,
|
||||
// JDK found at $JDK_19
|
||||
FULL_JDK_9,
|
||||
// JDK found at $JDK_15
|
||||
FULL_JDK_15,
|
||||
// JDK found at java.home
|
||||
FULL_JDK,
|
||||
ANDROID_API,
|
||||
}
|
||||
Reference in New Issue
Block a user