[TEST-GEN] Convert Test Generation DSL classes from java to kotlin

This commit is contained in:
Dmitriy Novozhilov
2020-11-06 18:08:26 +03:00
parent 31bccb4fb0
commit 2acbe96f15
5 changed files with 315 additions and 552 deletions
@@ -13,58 +13,27 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.generators.tests.generator
package org.jetbrains.kotlin.generators.tests.generator; open class DelegatingTestClassModel(private val delegate: TestClassModel) : TestClassModel() {
override val name: String
get() = delegate.name
import org.jetbrains.annotations.NotNull; override val innerTestClasses: Collection<TestClassModel>
import org.jetbrains.annotations.Nullable; get() = delegate.innerTestClasses
import java.util.Collection; override val methods: Collection<MethodModel>
get() = delegate.methods
public class DelegatingTestClassModel extends TestClassModel { override val isEmpty: Boolean
private final TestClassModel delegate; get() = delegate.isEmpty
public DelegatingTestClassModel(TestClassModel delegate) { override val dataPathRoot: String?
this.delegate = delegate; get() = delegate.dataPathRoot
}
@NotNull override val dataString: String?
@Override get() = delegate.dataString
public String getName() {
return delegate.getName();
}
@NotNull override val annotations: Collection<AnnotationModel>
@Override get() = delegate.annotations
public Collection<TestClassModel> getInnerTestClasses() {
return delegate.getInnerTestClasses();
}
@NotNull
@Override
public Collection<MethodModel> getMethods() {
return delegate.getMethods();
}
@Override
public boolean isEmpty() {
return delegate.isEmpty();
}
@Nullable
@Override
public String getDataPathRoot() {
return delegate.getDataPathRoot();
}
@Override
public String getDataString() {
return delegate.getDataString();
}
@NotNull
@Override
public Collection<AnnotationModel> getAnnotations() {
return delegate.getAnnotations();
}
} }
@@ -2,268 +2,189 @@
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * 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. * 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; import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.generators.tests.generator.TestGeneratorUtil.fileNameToJavaIdentifier
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.utils.Printer
import java.io.File
import java.util.*
import java.util.regex.Pattern
import com.intellij.openapi.util.io.FileUtil; class SimpleTestClassModel(
import com.intellij.openapi.util.text.StringUtil; private val rootFile: File,
import org.jetbrains.annotations.NotNull; private val recursive: Boolean,
import org.jetbrains.annotations.Nullable; private val excludeParentDirs: Boolean,
import org.jetbrains.kotlin.test.KotlinTestUtils; private val filenamePattern: Pattern,
import org.jetbrains.kotlin.test.TargetBackend; private val excludePattern: Pattern?,
import org.jetbrains.kotlin.utils.Printer; private val checkFilenameStartsLowerCase: Boolean?,
private val doTestMethodName: String,
private val testClassName: String,
private val targetBackend: TargetBackend,
excludeDirs: Collection<String>,
private val skipIgnored: Boolean,
private val testRunnerMethodName: String,
private val additionalRunnerArguments: List<String>,
private val deep: Int?,
override val annotations: Collection<AnnotationModel>,
) : TestClassModel() {
override val name: String
get() = testClassName
import java.io.File; private val excludeDirs: Set<String> = excludeDirs.toSet()
import java.util.*;
import java.util.regex.Pattern;
public class SimpleTestClassModel extends TestClassModel { override val innerTestClasses: Collection<TestClassModel> by lazy {
private static final Comparator<TestEntityModel> BY_NAME = Comparator.comparing(TestEntityModel::getName); if (!rootFile.isDirectory || !recursive || deep != null && deep < 1) {
return@lazy emptyList()
@NotNull }
private final File rootFile; val children = mutableListOf<TestClassModel>()
private final boolean recursive; val files = rootFile.listFiles() ?: return@lazy emptyList()
private final boolean excludeParentDirs; for (file in files) {
@NotNull if (file.isDirectory && dirHasFilesInside(file) && !excludeDirs.contains(file.name)) {
private final Pattern filenamePattern; val innerTestClassName = fileNameToJavaIdentifier(file)
@Nullable children.add(
private final Pattern excludePattern; SimpleTestClassModel(
@Nullable file,
private final Boolean checkFilenameStartsLowerCase; true,
@NotNull excludeParentDirs,
private final String doTestMethodName; filenamePattern,
@NotNull excludePattern,
private final String testClassName; checkFilenameStartsLowerCase,
private final Integer deep; doTestMethodName,
@NotNull innerTestClassName,
private final TargetBackend targetBackend; targetBackend,
@NotNull excludesStripOneDirectory(file.name),
private final Set<String> excludeDirs; skipIgnored,
@Nullable testRunnerMethodName,
private Collection<TestClassModel> innerTestClasses; additionalRunnerArguments,
@Nullable if (deep != null) deep - 1 else null,
private Collection<MethodModel> testMethods; annotations,
)
@NotNull )
private final Collection<AnnotationModel> annotations; }
}
private final boolean skipIgnored; children.sortWith(BY_NAME)
private final String testRunnerMethodName; children
private final List<String> additionalRunnerArguments;
public SimpleTestClassModel(
@NotNull File rootFile,
boolean recursive,
boolean excludeParentDirs,
@NotNull Pattern filenamePattern,
@Nullable Pattern excludedPattern,
@Nullable Boolean checkFilenameStartsLowerCase,
@NotNull String doTestMethodName,
@NotNull String testClassName,
@NotNull TargetBackend targetBackend,
@NotNull Collection<String> excludeDirs,
boolean skipIgnored,
String testRunnerMethodName,
List<String> additionalRunnerArguments,
Integer deep,
@NotNull Collection<AnnotationModel> annotations
) {
this.rootFile = rootFile;
this.recursive = recursive;
this.excludeParentDirs = excludeParentDirs;
this.filenamePattern = filenamePattern;
this.excludePattern = excludedPattern;
this.doTestMethodName = doTestMethodName;
this.testClassName = testClassName;
this.targetBackend = targetBackend;
this.checkFilenameStartsLowerCase = checkFilenameStartsLowerCase;
this.excludeDirs = excludeDirs.isEmpty() ? Collections.emptySet() : new LinkedHashSet<>(excludeDirs);
this.skipIgnored = skipIgnored;
this.testRunnerMethodName = testRunnerMethodName;
this.additionalRunnerArguments = additionalRunnerArguments;
this.deep = deep;
this.annotations = annotations;
} }
@NotNull
@Override private fun excludesStripOneDirectory(directoryName: String): Set<String> {
public Collection<TestClassModel> getInnerTestClasses() { if (excludeDirs.isEmpty()) return excludeDirs
if (!rootFile.isDirectory() || !recursive || deep != null && deep < 1) { val result: MutableSet<String> = LinkedHashSet()
return Collections.emptyList(); for (excludeDir in excludeDirs) {
val firstSlash = excludeDir.indexOf('/')
if (firstSlash >= 0 && excludeDir.substring(0, firstSlash) == directoryName) {
result.add(excludeDir.substring(firstSlash + 1))
}
} }
return result
}
if (innerTestClasses == null) { override val methods: Collection<MethodModel> by lazy {
List<TestClassModel> children = new ArrayList<>(); if (!rootFile.isDirectory) {
File[] files = rootFile.listFiles(); return@lazy listOf(
if (files != null) { SimpleTestMethodModel(
for (File file : files) { rootFile, rootFile, filenamePattern, checkFilenameStartsLowerCase, targetBackend, skipIgnored
if (file.isDirectory() && dirHasFilesInside(file) && !excludeDirs.contains(file.getName())) { )
String innerTestClassName = TestGeneratorUtil.fileNameToJavaIdentifier(file); )
children.add(new SimpleTestClassModel( }
file, true, excludeParentDirs, filenamePattern, excludePattern, checkFilenameStartsLowerCase, val result = mutableListOf<MethodModel>()
doTestMethodName, innerTestClassName, targetBackend, excludesStripOneDirectory(file.getName()), result.add(RunTestMethodModel(targetBackend, doTestMethodName, testRunnerMethodName, additionalRunnerArguments))
skipIgnored, testRunnerMethodName, additionalRunnerArguments, deep != null ? deep - 1 : null, annotations result.add(TestAllFilesPresentMethodModel())
) val listFiles = rootFile.listFiles()
); if (listFiles != null && (deep == null || deep == 0)) {
for (file in listFiles) {
val excluded = excludePattern != null && excludePattern.matcher(file.name).matches()
if (filenamePattern.matcher(file.name).matches() && !excluded) {
if (file.isDirectory && excludeParentDirs && dirHasSubDirs(file)) {
continue
} }
result.add(
SimpleTestMethodModel(
rootFile, file, filenamePattern,
checkFilenameStartsLowerCase, targetBackend, skipIgnored
)
)
} }
} }
children.sort(BY_NAME);
innerTestClasses = children;
} }
return innerTestClasses; result.sortWith(BY_NAME)
result
} }
@NotNull override val isEmpty: Boolean
private Set<String> excludesStripOneDirectory(@NotNull String directoryName) { get() {
if (excludeDirs.isEmpty()) return excludeDirs; val noTestMethods = methods.size == 1
return noTestMethods && innerTestClasses.isEmpty()
}
Set<String> result = new LinkedHashSet<>(); override val dataString: String
for (String excludeDir : excludeDirs) { get() = KotlinTestUtils.getFilePath(rootFile)
int firstSlash = excludeDir.indexOf('/');
if (firstSlash >= 0 && excludeDir.substring(0, firstSlash).equals(directoryName)) { override val dataPathRoot: String
result.add(excludeDir.substring(firstSlash + 1)); get() = "\$PROJECT_ROOT"
private inner class TestAllFilesPresentMethodModel : TestMethodModel() {
override val name: String
get() = "testAllFilesPresentIn$testClassName"
override val dataString: String?
get() = null
override fun generateBody(p: Printer) {
val exclude = StringBuilder()
for (dir in excludeDirs) {
exclude.append(", \"")
exclude.append(StringUtil.escapeStringCharacters(dir))
exclude.append("\"")
} }
} val excludedArgument = if (excludePattern != null) {
String.format("Pattern.compile(\"%s\")", StringUtil.escapeStringCharacters(excludePattern.pattern()))
return result; } else {
} null
private static boolean dirHasFilesInside(@NotNull File dir) {
return !FileUtil.processFilesRecursively(dir, File::isDirectory);
}
private static boolean dirHasSubDirs(@NotNull File dir) {
File[] listFiles = dir.listFiles();
if (listFiles == null) {
return false;
}
for (File file : listFiles) {
if (file.isDirectory()) {
return true;
} }
val assertTestsPresentStr = if (targetBackend === TargetBackend.ANY) {
String.format(
"KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File(\"%s\"), Pattern.compile(\"%s\"), %s, %s%s);",
KotlinTestUtils.getFilePath(rootFile),
StringUtil.escapeStringCharacters(filenamePattern.pattern()),
excludedArgument,
recursive,
exclude
)
} else {
String.format(
"KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File(\"%s\"), Pattern.compile(\"%s\"), %s, %s.%s, %s%s);",
KotlinTestUtils.getFilePath(rootFile), StringUtil.escapeStringCharacters(filenamePattern.pattern()),
excludedArgument, TargetBackend::class.java.simpleName, targetBackend.toString(), recursive, exclude
)
}
p.println(assertTestsPresentStr)
}
override fun shouldBeGenerated(): Boolean {
return true
} }
return false;
} }
@NotNull companion object {
@Override private val BY_NAME = Comparator.comparing(TestEntityModel::name)
public Collection<MethodModel> getMethods() {
if (testMethods == null) {
if (!rootFile.isDirectory()) {
testMethods = Collections.singletonList(new SimpleTestMethodModel(
rootFile, rootFile, filenamePattern, checkFilenameStartsLowerCase, targetBackend, skipIgnored
));
}
else {
List<MethodModel> result = new ArrayList<>();
result.add(new RunTestMethodModel(targetBackend, doTestMethodName, testRunnerMethodName, additionalRunnerArguments)); private fun dirHasFilesInside(dir: File): Boolean {
return !FileUtil.processFilesRecursively(dir) { obj: File -> obj.isDirectory }
}
result.add(new TestAllFilesPresentMethodModel()); private fun dirHasSubDirs(dir: File): Boolean {
val listFiles = dir.listFiles() ?: return false
File[] listFiles = rootFile.listFiles(); for (file in listFiles) {
if (file.isDirectory) {
if (listFiles != null && (deep == null || deep == 0)) { return true
for (File file : listFiles) {
boolean excluded = excludePattern != null && excludePattern.matcher(file.getName()).matches();
if (filenamePattern.matcher(file.getName()).matches() && !excluded) {
if (file.isDirectory() && excludeParentDirs && dirHasSubDirs(file)) {
continue;
}
result.add(new SimpleTestMethodModel(rootFile, file, filenamePattern, checkFilenameStartsLowerCase, targetBackend, skipIgnored));
}
}
} }
result.sort(BY_NAME);
testMethods = result;
} }
} return false
return testMethods;
}
@Override
public boolean isEmpty() {
boolean noTestMethods = getMethods().size() == 1;
return noTestMethods && getInnerTestClasses().isEmpty();
}
@Override
public String getDataString() {
return KotlinTestUtils.getFilePath(rootFile);
}
@Nullable
@Override
public String getDataPathRoot() {
return "$PROJECT_ROOT";
}
@NotNull
@Override
public String getName() {
return testClassName;
}
@NotNull
@Override
public Collection<AnnotationModel> getAnnotations() {
return annotations;
}
private class TestAllFilesPresentMethodModel extends TestMethodModel {
@NotNull
@Override
public String getName() {
return "testAllFilesPresentIn" + testClassName;
}
@Override
public void generateBody(@NotNull Printer p) {
StringBuilder exclude = new StringBuilder();
for (String dir : excludeDirs) {
exclude.append(", \"");
exclude.append(StringUtil.escapeStringCharacters(dir));
exclude.append("\"");
}
String excludedArgument;
if (excludePattern != null) {
excludedArgument = String.format("Pattern.compile(\"%s\")", StringUtil.escapeStringCharacters(excludePattern.pattern()));
} else {
excludedArgument = null;
}
String assertTestsPresentStr;
if (targetBackend == TargetBackend.ANY) {
assertTestsPresentStr = String.format(
"KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File(\"%s\"), Pattern.compile(\"%s\"), %s, %s%s);",
KotlinTestUtils.getFilePath(rootFile), StringUtil.escapeStringCharacters(filenamePattern.pattern()), excludedArgument, recursive, exclude
);
} else {
assertTestsPresentStr = String.format(
"KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File(\"%s\"), Pattern.compile(\"%s\"), %s, %s.%s, %s%s);",
KotlinTestUtils.getFilePath(rootFile), StringUtil.escapeStringCharacters(filenamePattern.pattern()),
excludedArgument, TargetBackend.class.getSimpleName(), targetBackend.toString(), recursive, exclude
);
}
p.println(assertTestsPresentStr);
}
@Override
public String getDataString() {
return null;
}
@Override
public boolean shouldBeGenerated() {
return true;
} }
} }
} }
@@ -2,100 +2,65 @@
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors. * 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. * 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; import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.generators.tests.generator.TestGeneratorUtil.escapeForJavaIdentifier
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.utils.Printer
import java.io.File
import java.util.regex.Pattern
import com.intellij.openapi.util.io.FileUtil; open class SimpleTestMethodModel(
import kotlin.text.StringsKt; private val rootDir: File,
import org.jetbrains.annotations.NotNull; protected val file: File,
import org.jetbrains.annotations.Nullable; private val filenamePattern: Pattern,
import org.jetbrains.kotlin.test.InTextDirectivesUtils; checkFilenameStartsLowerCase: Boolean?,
import org.jetbrains.kotlin.test.KotlinTestUtils; protected val targetBackend: TargetBackend,
import org.jetbrains.kotlin.test.TargetBackend; private val skipIgnored: Boolean
import org.jetbrains.kotlin.utils.Printer; ) : TestMethodModel() {
override fun generateBody(p: Printer) {
val filePath = KotlinTestUtils.getFilePath(file) + if (file.isDirectory) "/" else ""
p.println(RunTestMethodModel.METHOD_NAME, "(\"", filePath, "\");")
}
import java.io.File; override val dataString: String
import java.util.regex.Matcher; get() {
import java.util.regex.Pattern; val path = FileUtil.getRelativePath(rootDir, file)!!
return KotlinTestUtils.getFilePath(File(path))
}
import static org.jetbrains.kotlin.test.InTextDirectivesUtils.isIgnoredTarget; override fun shouldBeGenerated(): Boolean {
return InTextDirectivesUtils.isCompatibleTarget(targetBackend, file)
}
public class SimpleTestMethodModel extends TestMethodModel { override val name: String
get() {
@NotNull val matcher = filenamePattern.matcher(file.name)
private final File rootDir; val found = matcher.find()
@NotNull assert(found) { file.name + " isn't matched by regex " + filenamePattern.pattern() }
protected final File file; assert(matcher.groupCount() >= 1) { filenamePattern.pattern() }
@NotNull val extractedName = matcher.group(1) ?: error("extractedName should not be null: " + filenamePattern.pattern())
private final Pattern filenamePattern; val unescapedName = if (rootDir == file.parentFile) {
@NotNull extractedName
protected final TargetBackend targetBackend; } else {
val relativePath = FileUtil.getRelativePath(rootDir, file.parentFile)
private final boolean skipIgnored; relativePath + "-" + extractedName.capitalize()
}
public SimpleTestMethodModel( val ignored = skipIgnored && InTextDirectivesUtils.isIgnoredTarget(targetBackend, file)
@NotNull File rootDir, return (if (ignored) "ignore" else "test") + escapeForJavaIdentifier(unescapedName).capitalize()
@NotNull File file, }
@NotNull Pattern filenamePattern,
@Nullable Boolean checkFilenameStartsLowerCase,
@NotNull TargetBackend targetBackend,
boolean skipIgnored
) {
this.rootDir = rootDir;
this.file = file;
this.filenamePattern = filenamePattern;
this.targetBackend = targetBackend;
this.skipIgnored = skipIgnored;
init {
if (checkFilenameStartsLowerCase != null) { if (checkFilenameStartsLowerCase != null) {
char c = file.getName().charAt(0); val c = file.name[0]
if (checkFilenameStartsLowerCase) { if (checkFilenameStartsLowerCase) {
assert Character.isLowerCase(c) : "Invalid file name '" + file + "', file name should start with lower-case letter"; assert(Character.isLowerCase(c)) { "Invalid file name '$file', file name should start with lower-case letter" }
} } else {
else { assert(Character.isUpperCase(c)) { "Invalid file name '$file', file name should start with upper-case letter" }
assert Character.isUpperCase(c) : "Invalid file name '" + file + "', file name should start with upper-case letter";
} }
} }
} }
@Override
public void generateBody(@NotNull Printer p) {
String filePath = KotlinTestUtils.getFilePath(file) + (file.isDirectory() ? "/" : "");
p.println(RunTestMethodModel.METHOD_NAME, "(\"", filePath, "\");");
}
@Override
public String getDataString() {
String path = FileUtil.getRelativePath(rootDir, file);
assert path != null;
return KotlinTestUtils.getFilePath(new File(path));
}
@Override
public boolean shouldBeGenerated() {
return InTextDirectivesUtils.isCompatibleTarget(targetBackend, file);
}
@NotNull
@Override
public String getName() {
Matcher matcher = filenamePattern.matcher(file.getName());
boolean found = matcher.find();
assert found : file.getName() + " isn't matched by regex " + filenamePattern.pattern();
assert matcher.groupCount() >= 1 : filenamePattern.pattern();
String extractedName = matcher.group(1);
assert extractedName != null : "extractedName should not be null: " + filenamePattern.pattern();
String unescapedName;
if (rootDir.equals(file.getParentFile())) {
unescapedName = extractedName;
}
else {
String relativePath = FileUtil.getRelativePath(rootDir, file.getParentFile());
unescapedName = relativePath + "-" + StringsKt.capitalize(extractedName);
}
boolean ignored = skipIgnored && isIgnoredTarget(targetBackend, file);
return (ignored ? "ignore" : "test") + StringsKt.capitalize(TestGeneratorUtil.escapeForJavaIdentifier(unescapedName));
}
} }
@@ -13,184 +13,96 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.generators.tests.generator
package org.jetbrains.kotlin.generators.tests.generator; import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.utils.Printer
import java.io.File
import java.util.*
import java.util.regex.Pattern
import com.intellij.openapi.util.io.FileUtil; class SingleClassTestModel(
import com.intellij.openapi.util.text.StringUtil; private val rootFile: File,
import kotlin.collections.CollectionsKt; private val filenamePattern: Pattern,
import org.jetbrains.annotations.NotNull; private val excludePattern: Pattern?,
import org.jetbrains.annotations.Nullable; private val checkFilenameStartsLowerCase: Boolean?,
import org.jetbrains.kotlin.test.KotlinTestUtils; private val doTestMethodName: String,
import org.jetbrains.kotlin.test.TargetBackend; private val testClassName: String,
import org.jetbrains.kotlin.utils.Printer; private val targetBackend: TargetBackend,
private val skipIgnored: Boolean,
private val testRunnerMethodName: String,
private val additionalRunnerArguments: List<String>,
override val annotations: List<AnnotationModel>
) : TestClassModel() {
override val name: String
get() = testClassName
import java.io.File; override val methods: Collection<MethodModel> by lazy {
import java.util.ArrayList; val result: MutableList<MethodModel> = ArrayList()
import java.util.Collection; result.add(RunTestMethodModel(targetBackend, doTestMethodName, testRunnerMethodName, additionalRunnerArguments))
import java.util.Collections; result.add(TestAllFilesPresentMethodModel())
import java.util.List; FileUtil.processFilesRecursively(rootFile) { file: File ->
import java.util.regex.Pattern; if (!file.isDirectory && filenamePattern.matcher(file.name).matches()) {
import java.util.stream.Collectors; result.addAll(getTestMethodsFromFile(file))
}
public class SingleClassTestModel extends TestClassModel { true
@NotNull
private final File rootFile;
@NotNull
private final Pattern filenamePattern;
@Nullable
private final Pattern excludePattern;
@Nullable
private final Boolean checkFilenameStartsLowerCase;
@NotNull
private final String doTestMethodName;
@NotNull
private final String testClassName;
@NotNull
private final TargetBackend targetBackend;
@Nullable
private Collection<MethodModel> methods;
private final boolean skipIgnored;
private final String testRunnerMethodName;
private final List<String> additionalRunnerArguments;
@NotNull
private final List<AnnotationModel> annotations;
public SingleClassTestModel(
@NotNull File rootFile,
@NotNull Pattern filenamePattern,
@Nullable Pattern excludePattern,
@Nullable Boolean checkFilenameStartsLowerCase,
@NotNull String doTestMethodName,
@NotNull String testClassName,
@NotNull TargetBackend targetBackend,
boolean skipIgnored,
String testRunnerMethodName,
List<String> additionalRunnerArguments,
@NotNull List<AnnotationModel> annotations
) {
this.rootFile = rootFile;
this.filenamePattern = filenamePattern;
this.excludePattern = excludePattern;
this.checkFilenameStartsLowerCase = checkFilenameStartsLowerCase;
this.doTestMethodName = doTestMethodName;
this.testClassName = testClassName;
this.targetBackend = targetBackend;
this.skipIgnored = skipIgnored;
this.testRunnerMethodName = testRunnerMethodName;
this.additionalRunnerArguments = additionalRunnerArguments;
this.annotations = annotations;
}
@NotNull
@Override
public final Collection<TestClassModel> getInnerTestClasses() {
return Collections.emptyList();
}
@NotNull
@Override
public Collection<MethodModel> getMethods() {
if (methods == null) {
List<MethodModel> result = new ArrayList<>();
result.add(new RunTestMethodModel(targetBackend, doTestMethodName, testRunnerMethodName, additionalRunnerArguments));
result.add(new TestAllFilesPresentMethodModel());
FileUtil.processFilesRecursively(rootFile, file -> {
if (!file.isDirectory() && filenamePattern.matcher(file.getName()).matches()) {
result.addAll(getTestMethodsFromFile(file));
}
return true;
});
methods = CollectionsKt.sortedWith(result, (o1, o2) -> o1.getName().compareToIgnoreCase(o2.getName()));
} }
result.sortedWith { o1: MethodModel, o2: MethodModel -> o1.name.compareTo(o2.name, ignoreCase = true) }
return methods;
} }
@NotNull override val innerTestClasses: Collection<TestClassModel>
private Collection<TestMethodModel> getTestMethodsFromFile(File file) { get() = emptyList()
return Collections.singletonList(new SimpleTestMethodModel(
private fun getTestMethodsFromFile(file: File): Collection<TestMethodModel> {
return listOf(
SimpleTestMethodModel(
rootFile, file, filenamePattern, checkFilenameStartsLowerCase, targetBackend, skipIgnored rootFile, file, filenamePattern, checkFilenameStartsLowerCase, targetBackend, skipIgnored
)); )
)
} }
@Override // There's always one test for checking if all tests are present
public boolean isEmpty() { override val isEmpty: Boolean
// There's always one test for checking if all tests are present get() = methods.size <= 1
return getMethods().size() <= 1; override val dataString: String = KotlinTestUtils.getFilePath(rootFile)
} override val dataPathRoot: String = "\$PROJECT_ROOT"
@Override private inner class TestAllFilesPresentMethodModel : TestMethodModel() {
public String getDataString() { override val name: String = "testAllFilesPresentIn$testClassName"
return KotlinTestUtils.getFilePath(rootFile); override val dataString: String?
} get() = null
@Nullable override fun generateBody(p: Printer) {
@Override val assertTestsPresentStr: String
public String getDataPathRoot() { val excludedArgument = if (excludePattern != null) {
return "$PROJECT_ROOT"; String.format(
} "Pattern.compile(\"%s\")", StringUtil.escapeStringCharacters(
excludePattern.pattern()
@NotNull )
@Override )
public String getName() {
return testClassName;
}
@NotNull
@Override
public Collection<AnnotationModel> getAnnotations() {
return annotations;
}
private class TestAllFilesPresentMethodModel extends TestMethodModel {
@NotNull
@Override
public String getName() {
return "testAllFilesPresentIn" + testClassName;
}
@Override
public void generateBody(@NotNull Printer p) {
String assertTestsPresentStr;
String excludedArgument;
if (excludePattern != null) {
excludedArgument = String.format("Pattern.compile(\"%s\")", StringUtil.escapeStringCharacters(excludePattern.pattern()));
} else { } else {
excludedArgument = null; null
} }
assertTestsPresentStr = if (targetBackend !== TargetBackend.ANY) {
if (targetBackend != TargetBackend.ANY) { String.format(
assertTestsPresentStr = String.format( "KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClassWithExcluded(this.getClass(), new File(\"%s\"), Pattern.compile(\"%s\"), %s, %s.%s);",
"KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClassWithExcluded(this.getClass(), new File(\"%s\"), Pattern.compile(\"%s\"), %s, %s.%s);", KotlinTestUtils.getFilePath(rootFile), StringUtil.escapeStringCharacters(filenamePattern.pattern()),
KotlinTestUtils.getFilePath(rootFile), StringUtil.escapeStringCharacters(filenamePattern.pattern()), excludedArgument, TargetBackend::class.java.simpleName, targetBackend.toString()
excludedArgument, TargetBackend.class.getSimpleName(), targetBackend.toString() )
);
} else { } else {
assertTestsPresentStr = String.format( String.format(
"KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClassWithExcluded(this.getClass(), new File(\"%s\"), Pattern.compile(\"%s\"), %s);", "KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClassWithExcluded(this.getClass(), new File(\"%s\"), Pattern.compile(\"%s\"), %s);",
KotlinTestUtils.getFilePath(rootFile), StringUtil.escapeStringCharacters(filenamePattern.pattern()), excludedArgument KotlinTestUtils.getFilePath(rootFile), StringUtil.escapeStringCharacters(filenamePattern.pattern()), excludedArgument
); )
} }
p.println(assertTestsPresentStr); p.println(assertTestsPresentStr)
} }
@Override override fun shouldBeGenerated(): Boolean {
public String getDataString() { return true
return null;
}
@Override
public boolean shouldBeGenerated() {
return true;
} }
} }
} }
@@ -13,34 +13,30 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.generators.tests.generator
package org.jetbrains.kotlin.generators.tests.generator; import kotlin.text.capitalize
import org.jetbrains.kotlin.generators.tests.generator.TestGeneratorUtil
import java.io.File
import java.lang.StringBuilder
import kotlin.text.StringsKt; object TestGeneratorUtil {
import org.jetbrains.annotations.NotNull; @JvmStatic
fun escapeForJavaIdentifier(fileName: String): String {
import java.io.File;
public class TestGeneratorUtil {
@NotNull
public static String escapeForJavaIdentifier(String fileName) {
// A file name may contain characters (like ".") that can't be a part of method name // A file name may contain characters (like ".") that can't be a part of method name
StringBuilder result = new StringBuilder(); val result = StringBuilder()
for (int i = 0; i < fileName.length(); i++) { for (c in fileName) {
char c = fileName.charAt(i);
if (Character.isJavaIdentifierPart(c)) { if (Character.isJavaIdentifierPart(c)) {
result.append(c); result.append(c)
} } else {
else { result.append("_")
result.append("_");
} }
} }
return result.toString(); return result.toString()
} }
@NotNull @JvmStatic
public static String fileNameToJavaIdentifier(@NotNull File file) { fun fileNameToJavaIdentifier(file: File): String {
return StringsKt.capitalize(escapeForJavaIdentifier(file.getName())); return escapeForJavaIdentifier(file.name).capitalize()
} }
} }