[TEST-GEN] Create abstract TestGenerator and move current generator logic to TestGeneratorImpl
This commit is contained in:
+6
-12
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.generators.tests.generator
|
|||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
import org.jetbrains.kotlin.generators.tests.generator.InconsistencyChecker.Companion.hasDryRunArg
|
import org.jetbrains.kotlin.generators.tests.generator.InconsistencyChecker.Companion.hasDryRunArg
|
||||||
import org.jetbrains.kotlin.generators.tests.generator.InconsistencyChecker.Companion.inconsistencyChecker
|
import org.jetbrains.kotlin.generators.tests.generator.InconsistencyChecker.Companion.inconsistencyChecker
|
||||||
|
import org.jetbrains.kotlin.generators.tests.generator.generators.TestGenerator
|
||||||
import org.jetbrains.kotlin.generators.tests.generator.generators.impl.*
|
import org.jetbrains.kotlin.generators.tests.generator.generators.impl.*
|
||||||
import org.jetbrains.kotlin.test.TargetBackend
|
import org.jetbrains.kotlin.test.TargetBackend
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -38,23 +39,16 @@ class TestGroup(
|
|||||||
annotations: List<AnnotationModel> = emptyList(),
|
annotations: List<AnnotationModel> = emptyList(),
|
||||||
init: TestClass.() -> Unit
|
init: TestClass.() -> Unit
|
||||||
) {
|
) {
|
||||||
val testGenerator = TestGenerator(
|
val generationData = TestGenerator.GenerationData(
|
||||||
testsRoot,
|
testsRoot,
|
||||||
suiteTestClassName,
|
suiteTestClassName,
|
||||||
baseTestClassName,
|
baseTestClassName,
|
||||||
TestClass(annotations).apply(init).testModels,
|
TestClass(annotations).apply(init).testModels,
|
||||||
useJunit4,
|
useJunit4,
|
||||||
methodGenerators = listOf(
|
|
||||||
CoroutinesTestMethodGenerator,
|
|
||||||
RunTestMethodGenerator,
|
|
||||||
RunTestMethodWithPackageReplacementGenerator,
|
|
||||||
SimpleTestClassModelTestAllFilesPresentMethodGenerator,
|
|
||||||
SimpleTestMethodGenerator,
|
|
||||||
SingleClassTestModelAllFilesPresentedMethodGenerator
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
if (testGenerator.generateAndSave(dryRun)) {
|
val (changed, testSourceFilePath) = TestGeneratorImpl.generateAndSave(generationData, dryRun)
|
||||||
inconsistencyChecker(dryRun).add(testGenerator.testSourceFilePath)
|
if (changed) {
|
||||||
|
inconsistencyChecker(dryRun).add(testSourceFilePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +63,7 @@ class TestGroup(
|
|||||||
pattern: String = if (extension == null) """^([^\.]+)$""" else "^(.+)\\.$extension\$",
|
pattern: String = if (extension == null) """^([^\.]+)$""" else "^(.+)\\.$extension\$",
|
||||||
excludedPattern: String? = null,
|
excludedPattern: String? = null,
|
||||||
testMethod: String = "doTest",
|
testMethod: String = "doTest",
|
||||||
singleClass: Boolean = false, // if true then tests from subdirectories will be flattern to single class
|
singleClass: Boolean = false, // if true then tests from subdirectories will be flatten to single class
|
||||||
testClassName: String? = null, // specific name for generated test class
|
testClassName: String? = null, // specific name for generated test class
|
||||||
// which backend will be used in test. Specifying value may affect some test with
|
// which backend will be used in test. Specifying value may affect some test with
|
||||||
// directives TARGET_BACKEND/DONT_TARGET_EXACT_BACKEND won't be generated
|
// directives TARGET_BACKEND/DONT_TARGET_EXACT_BACKEND won't be generated
|
||||||
|
|||||||
+2
-2
@@ -17,6 +17,6 @@ abstract class MethodGenerator<in T : MethodModel> {
|
|||||||
|
|
||||||
abstract val kind: MethodModel.Kind
|
abstract val kind: MethodModel.Kind
|
||||||
|
|
||||||
abstract fun generateSignature(method: @UnsafeVariance T, p: Printer)
|
abstract fun generateSignature(method: T, p: Printer)
|
||||||
abstract fun generateBody(method: @UnsafeVariance T, p: Printer)
|
abstract fun generateBody(method: T, p: Printer)
|
||||||
}
|
}
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 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.tests.generator.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.generators.tests.generator.MethodModel
|
||||||
|
import org.jetbrains.kotlin.generators.tests.generator.TestClassModel
|
||||||
|
|
||||||
|
abstract class TestGenerator(
|
||||||
|
methodGenerators: List<MethodGenerator<*>>
|
||||||
|
) {
|
||||||
|
protected val methodGenerators: Map<MethodModel.Kind, MethodGenerator<*>> =
|
||||||
|
methodGenerators.associateBy { it.kind }.withDefault { error("Generator for method with kind $it not found") }
|
||||||
|
|
||||||
|
abstract fun generateAndSave(data: GenerationData, dryRun: Boolean): GenerationResult
|
||||||
|
|
||||||
|
data class GenerationData(
|
||||||
|
val baseDir: String,
|
||||||
|
val suiteTestClassFqName: String,
|
||||||
|
val baseTestClassFqName: String,
|
||||||
|
val testClassModels: Collection<TestClassModel>,
|
||||||
|
val useJunit4: Boolean
|
||||||
|
)
|
||||||
|
|
||||||
|
data class GenerationResult(val newFileGenerated: Boolean, val testSourceFilePath: String)
|
||||||
|
}
|
||||||
|
|
||||||
+77
-61
@@ -1,11 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2000-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
* 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.
|
* 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.tests.generator
|
package org.jetbrains.kotlin.generators.tests.generator.generators.impl
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.generators.tests.generator.*
|
||||||
import org.jetbrains.kotlin.generators.tests.generator.generators.MethodGenerator
|
import org.jetbrains.kotlin.generators.tests.generator.generators.MethodGenerator
|
||||||
|
import org.jetbrains.kotlin.generators.tests.generator.generators.TestGenerator
|
||||||
import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil
|
import org.jetbrains.kotlin.generators.util.GeneratorsFileUtil
|
||||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners
|
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
@@ -18,45 +20,81 @@ import java.io.File
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class TestGenerator(
|
private val METHOD_GENERATORS = listOf(
|
||||||
|
RunTestMethodGenerator,
|
||||||
|
SimpleTestClassModelTestAllFilesPresentMethodGenerator,
|
||||||
|
SimpleTestMethodGenerator,
|
||||||
|
SingleClassTestModelAllFilesPresentedMethodGenerator
|
||||||
|
)
|
||||||
|
|
||||||
|
object TestGeneratorImpl : TestGenerator(METHOD_GENERATORS) {
|
||||||
|
override fun generateAndSave(data: GenerationData, dryRun: Boolean): GenerationResult {
|
||||||
|
val (baseDir, suiteTestClassFqName, baseTestClassFqName, testClassModels, useJunit4) = data
|
||||||
|
val generatorInstance = TestGeneratorImplInstance(
|
||||||
|
baseDir,
|
||||||
|
suiteTestClassFqName,
|
||||||
|
baseTestClassFqName,
|
||||||
|
testClassModels,
|
||||||
|
useJunit4,
|
||||||
|
methodGenerators
|
||||||
|
)
|
||||||
|
return generatorInstance.generateAndSave(dryRun)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestGeneratorImplInstance(
|
||||||
baseDir: String,
|
baseDir: String,
|
||||||
suiteTestClassFqName: String,
|
suiteTestClassFqName: String,
|
||||||
baseTestClassFqName: String,
|
baseTestClassFqName: String,
|
||||||
testClassModels: Collection<TestClassModel>,
|
private val testClassModels: Collection<TestClassModel>,
|
||||||
useJunit4: Boolean,
|
private val useJunit4: Boolean,
|
||||||
methodGenerators: List<MethodGenerator<*>>
|
private val methodGenerators: Map<MethodModel.Kind, MethodGenerator<*>>
|
||||||
) {
|
) {
|
||||||
private val methodGenerators: Map<MethodModel.Kind, MethodGenerator<*>> =
|
companion object {
|
||||||
methodGenerators.associateBy { it.kind }.withDefault { error("Generator for method with kind $it not found") }
|
private val GENERATED_FILES = HashSet<String>()
|
||||||
|
private val RUNNER = JUnit3RunnerWithInners::class.java
|
||||||
|
private val JUNIT4_RUNNER = BlockJUnit4ClassRunner::class.java
|
||||||
|
|
||||||
private val baseTestClassPackage: String
|
private fun generateMetadata(p: Printer, testDataSource: TestEntityModel) {
|
||||||
private val suiteClassPackage: String
|
val dataString = testDataSource.dataString
|
||||||
private val suiteClassName: String
|
if (dataString != null) {
|
||||||
private val baseTestClassName: String
|
p.println("@TestMetadata(\"", dataString, "\")")
|
||||||
private val testClassModels: Collection<TestClassModel>
|
}
|
||||||
private val useJunit4: Boolean
|
}
|
||||||
internal val testSourceFilePath: String
|
|
||||||
|
|
||||||
init {
|
private fun generateTestDataPath(p: Printer, testClassModel: TestClassModel) {
|
||||||
this.baseTestClassPackage = baseTestClassFqName.substringBeforeLast('.', "")
|
val dataPathRoot = testClassModel.dataPathRoot
|
||||||
this.baseTestClassName = baseTestClassFqName.substringAfterLast('.', baseTestClassFqName)
|
if (dataPathRoot != null) {
|
||||||
this.suiteClassPackage = suiteTestClassFqName.substringBeforeLast('.', baseTestClassPackage)
|
p.println("@TestDataPath(\"", dataPathRoot, "\")")
|
||||||
this.suiteClassName = suiteTestClassFqName.substringAfterLast('.', suiteTestClassFqName)
|
}
|
||||||
this.testClassModels = ArrayList(testClassModels)
|
}
|
||||||
this.useJunit4 = useJunit4
|
|
||||||
|
|
||||||
this.testSourceFilePath = baseDir + "/" + this.suiteClassPackage.replace(".", "/") + "/" + this.suiteClassName + ".java"
|
private fun generateParameterAnnotations(p: Printer, testClassModel: TestClassModel) {
|
||||||
|
for (annotationModel in testClassModel.annotations) {
|
||||||
|
annotationModel.generate(p)
|
||||||
|
p.println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!GENERATED_FILES.add(testSourceFilePath)) {
|
private fun generateSuppressAllWarnings(p: Printer) {
|
||||||
throw IllegalArgumentException("Same test file already generated in current session: " + testSourceFilePath)
|
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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if a new file is generated
|
|
||||||
*/
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
fun generateAndSave(dryRun: Boolean): Boolean {
|
fun generateAndSave(dryRun: Boolean): TestGenerator.GenerationResult {
|
||||||
val generatedCode = generate()
|
val generatedCode = generate()
|
||||||
|
|
||||||
val testSourceFile = File(testSourceFilePath)
|
val testSourceFile = File(testSourceFilePath)
|
||||||
@@ -65,7 +103,7 @@ class TestGenerator(
|
|||||||
if (!dryRun) {
|
if (!dryRun) {
|
||||||
GeneratorsFileUtil.writeFileIfContentChanged(testSourceFile, generatedCode, false)
|
GeneratorsFileUtil.writeFileIfContentChanged(testSourceFile, generatedCode, false)
|
||||||
}
|
}
|
||||||
return changed
|
return TestGenerator.GenerationResult(changed, testSourceFilePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generate(): String {
|
private fun generate(): String {
|
||||||
@@ -201,47 +239,25 @@ class TestGenerator(
|
|||||||
val generator = methodGenerators.getValue(methodModel.kind)
|
val generator = methodGenerators.getValue(methodModel.kind)
|
||||||
|
|
||||||
generateMetadata(p, methodModel)
|
generateMetadata(p, methodModel)
|
||||||
generator.generateSignature(methodModel, p)
|
generator.hackyGenerateSignature(methodModel, p)
|
||||||
p.printWithNoIndent(" {")
|
p.printWithNoIndent(" {")
|
||||||
p.println()
|
p.println()
|
||||||
|
|
||||||
p.pushIndent()
|
p.pushIndent()
|
||||||
|
|
||||||
generator.generateBody(methodModel, p)
|
generator.hackyGenerateBody(methodModel, p)
|
||||||
|
|
||||||
p.popIndent()
|
p.popIndent()
|
||||||
p.println("}")
|
p.println("}")
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
private fun <T : MethodModel> MethodGenerator<T>.hackyGenerateBody(method: MethodModel, p: Printer) {
|
||||||
private val GENERATED_FILES = HashSet<String>()
|
@Suppress("UNCHECKED_CAST")
|
||||||
private val RUNNER = JUnit3RunnerWithInners::class.java
|
generateBody(method as T, p)
|
||||||
private val JUNIT4_RUNNER = BlockJUnit4ClassRunner::class.java
|
}
|
||||||
|
|
||||||
|
private fun <T : MethodModel> MethodGenerator<T>.hackyGenerateSignature(method: MethodModel, p: Printer) {
|
||||||
private fun generateMetadata(p: Printer, testDataSource: TestEntityModel) {
|
@Suppress("UNCHECKED_CAST")
|
||||||
val dataString = testDataSource.dataString
|
generateSignature(method as T, p)
|
||||||
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\")")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user