mirror of
https://github.com/ethauvin/kobalt.git
synced 2025-04-26 16:28:12 -07:00
Add includes/excludes to the test{} directives.
Original code from @bmsantos.
This commit is contained in:
parent
0a87a7684f
commit
eb2937098d
9 changed files with 96 additions and 84 deletions
|
@ -3,7 +3,9 @@ package com.beust.kobalt
|
||||||
import com.beust.kobalt.misc.log
|
import com.beust.kobalt.misc.log
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.*
|
import java.nio.file.*
|
||||||
|
import java.nio.file.FileVisitResult.CONTINUE
|
||||||
import java.nio.file.attribute.BasicFileAttributes
|
import java.nio.file.attribute.BasicFileAttributes
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
sealed class IFileSpec {
|
sealed class IFileSpec {
|
||||||
abstract fun toFiles(directory: String): List<File>
|
abstract fun toFiles(directory: String): List<File>
|
||||||
|
@ -14,25 +16,57 @@ sealed class IFileSpec {
|
||||||
override public fun toString() = spec
|
override public fun toString() = spec
|
||||||
}
|
}
|
||||||
|
|
||||||
class GlobSpec(val spec: String) : IFileSpec() {
|
class GlobSpec(val includeSpec: ArrayList<String>, val excludeSpec: ArrayList<String>) : IFileSpec() {
|
||||||
override public fun toFiles(directory: String): List<File> {
|
|
||||||
val result = arrayListOf<File>()
|
constructor(spec: String) : this(arrayListOf(spec), arrayListOf())
|
||||||
|
|
||||||
|
override public fun toFiles(directory: String): List<File> {
|
||||||
|
|
||||||
|
val result = arrayListOf<File>()
|
||||||
|
val includeMatchers = prepareMatchers(includeSpec.toTypedArray())
|
||||||
|
val excludeMatchers = prepareMatchers(excludeSpec.toTypedArray())
|
||||||
|
|
||||||
val matcher = FileSystems.getDefault().getPathMatcher("glob:$spec")
|
|
||||||
Files.walkFileTree(Paths.get(directory), object : SimpleFileVisitor<Path>() {
|
Files.walkFileTree(Paths.get(directory), object : SimpleFileVisitor<Path>() {
|
||||||
override public fun visitFile(path: Path, attrs: BasicFileAttributes): FileVisitResult {
|
override public fun visitFile(path: Path, attrs: BasicFileAttributes): FileVisitResult {
|
||||||
|
|
||||||
val rel = Paths.get(directory).relativize(path)
|
val rel = Paths.get(directory).relativize(path)
|
||||||
if (matcher.matches(rel)) {
|
excludeMatchers.forEach {
|
||||||
log(3, "Adding ${rel.toFile()}")
|
if (it.matches(rel)) {
|
||||||
result.add(rel.toFile())
|
log(3, "Removing ${rel.toFile()}")
|
||||||
|
return CONTINUE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return FileVisitResult.CONTINUE
|
includeMatchers.forEach {
|
||||||
|
if (it.matches(rel)) {
|
||||||
|
log(3, "Adding ${rel.toFile()}")
|
||||||
|
result.add(rel.toFile())
|
||||||
|
return CONTINUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CONTINUE
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override public fun toString() = spec
|
override public fun toString(): String {
|
||||||
|
var result = ""
|
||||||
|
includeSpec.apply {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
result += "Included files: " + joinToString { ", " }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
excludeSpec.apply {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
result += "Excluded files: " + joinToString { ", " }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun prepareMatchers(specs: Array<String>): List<PathMatcher> =
|
||||||
|
specs.map { it -> FileSystems.getDefault().getPathMatcher("glob:$it") }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -11,9 +11,21 @@ class TestConfig(val project: Project) {
|
||||||
fun jvmArgs(vararg arg: String) {
|
fun jvmArgs(vararg arg: String) {
|
||||||
project.testJvmArgs.addAll(arg)
|
project.testJvmArgs.addAll(arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun includes(vararg arg: String) {
|
||||||
|
project.testIncludes.apply {
|
||||||
|
clear()
|
||||||
|
addAll(arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun excludes(vararg arg: String) {
|
||||||
|
project.testExcludes.apply {
|
||||||
|
clear()
|
||||||
|
addAll(arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Directive
|
@Directive
|
||||||
fun Project.test(init: TestConfig.() -> Unit) = TestConfig(this).apply { init() }
|
fun Project.test(init: TestConfig.() -> Unit) = TestConfig(this).apply { init() }
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,8 @@ open class Project(
|
||||||
val testJvmArgs = arrayListOf<String>()
|
val testJvmArgs = arrayListOf<String>()
|
||||||
|
|
||||||
val projectProperties = ProjectProperties()
|
val projectProperties = ProjectProperties()
|
||||||
|
val testIncludes = arrayListOf("**/*Test.class")
|
||||||
|
val testExcludes = arrayListOf<String>()
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
return name == (other as Project).name
|
return name == (other as Project).name
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.beust.kobalt.internal
|
package com.beust.kobalt.internal
|
||||||
|
|
||||||
|
import com.beust.kobalt.IFileSpec
|
||||||
import com.beust.kobalt.JavaInfo
|
import com.beust.kobalt.JavaInfo
|
||||||
import com.beust.kobalt.SystemProperties
|
import com.beust.kobalt.SystemProperties
|
||||||
import com.beust.kobalt.TaskResult
|
import com.beust.kobalt.TaskResult
|
||||||
|
@ -7,7 +8,7 @@ import com.beust.kobalt.api.*
|
||||||
import com.beust.kobalt.misc.KFiles
|
import com.beust.kobalt.misc.KFiles
|
||||||
import com.beust.kobalt.misc.log
|
import com.beust.kobalt.misc.log
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLClassLoader
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for testing frameworks that are invoked from a main class with arguments. Test runners can
|
* Base class for testing frameworks that are invoked from a main class with arguments. Test runners can
|
||||||
|
@ -25,33 +26,21 @@ abstract class GenericTestRunner : ITestRunnerContributor {
|
||||||
if (project.testDependencies.any { it.id.contains(dependencyName)}) IAffinity.DEFAULT_POSITIVE_AFFINITY
|
if (project.testDependencies.any { it.id.contains(dependencyName)}) IAffinity.DEFAULT_POSITIVE_AFFINITY
|
||||||
else 0
|
else 0
|
||||||
|
|
||||||
protected fun findTestClasses(project: Project, classpath: List<IClasspathDependency>,
|
protected fun findTestClasses(project: Project): List<String> {
|
||||||
classFilter : (Class<*>) -> Boolean = {true}): List<String> {
|
|
||||||
val path = KFiles.joinDir(project.directory, project.buildDirectory, KFiles.TEST_CLASSES_DIR)
|
val path = KFiles.joinDir(project.directory, project.buildDirectory, KFiles.TEST_CLASSES_DIR)
|
||||||
val result = KFiles.findRecursively(File(path), arrayListOf(File(".")), {
|
|
||||||
file -> file.endsWith(".class")
|
|
||||||
}).map {
|
|
||||||
it.replace("/", ".").replace("\\", ".").replace(".class", "").substring(2)
|
|
||||||
}.filter {
|
|
||||||
try {
|
|
||||||
// Only keep classes with a parameterless constructor
|
|
||||||
val urls = arrayOf(File(path).toURI().toURL()) +
|
|
||||||
classpath.map { it.jarFile.get().toURI().toURL() }
|
|
||||||
val cl = URLClassLoader(urls).loadClass(it)
|
|
||||||
val constructor = cl.getConstructor()
|
|
||||||
// If we get past this, we have a default constructor
|
|
||||||
|
|
||||||
classFilter(cl)
|
val result = IFileSpec.GlobSpec(toClassPaths(project.testIncludes), toClassPaths(project.testExcludes))
|
||||||
} catch(ex: Exception) {
|
.toFiles(path).map {
|
||||||
log(2, "Skipping non test class $it: ${ex.message}")
|
it.toString().replace("/", ".").replace("\\", ".").replace(".class", "")
|
||||||
false
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log(2, "Found ${result.size} test classes")
|
log(2, "Found ${result.size} test classes")
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun toClassPaths(paths: List<String>): ArrayList<String> =
|
||||||
|
paths.map { if (it.endsWith(".class")) it else it + ".class" }.toArrayList()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if all the tests passed
|
* @return true if all the tests passed
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,15 +9,6 @@ open public class JUnitRunner() : GenericTestRunner() {
|
||||||
|
|
||||||
override val dependencyName = "junit"
|
override val dependencyName = "junit"
|
||||||
|
|
||||||
override fun args(project: Project, classpath: List<IClasspathDependency>)
|
override fun args(project: Project, classpath: List<IClasspathDependency>) = findTestClasses(project)
|
||||||
= findTestClasses(project, classpath) {
|
|
||||||
// Only return a class if it contains at least one @Test method, otherwise
|
|
||||||
// JUnit 4 throws an exception :-(
|
|
||||||
it.declaredMethods.flatMap {
|
|
||||||
it.annotations.toList()
|
|
||||||
}.filter {
|
|
||||||
ann: Annotation -> ann.javaClass.name.contains("Test")
|
|
||||||
}.size > 0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,18 +15,18 @@ public class TestNgRunner() : GenericTestRunner() {
|
||||||
override fun args(project: Project, classpath: List<IClasspathDependency>) = arrayListOf<String>().apply {
|
override fun args(project: Project, classpath: List<IClasspathDependency>) = arrayListOf<String>().apply {
|
||||||
if (project.testArgs.size > 0) {
|
if (project.testArgs.size > 0) {
|
||||||
addAll(project.testArgs)
|
addAll(project.testArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
val testngXml = File(project.directory, KFiles.joinDir("src", "test", "resources", "testng.xml"))
|
||||||
|
if (testngXml.exists()) {
|
||||||
|
add(testngXml.absolutePath)
|
||||||
} else {
|
} else {
|
||||||
val testngXml = File(project.directory, KFiles.joinDir("src", "test", "resources", "testng.xml"))
|
val testClasses = findTestClasses(project)
|
||||||
if (testngXml.exists()) {
|
if (testClasses.size > 0) {
|
||||||
add(testngXml.absolutePath)
|
add("-testclass")
|
||||||
|
add(testClasses.joinToString(","))
|
||||||
} else {
|
} else {
|
||||||
val testClasses = findTestClasses(project, classpath)
|
warn("Couldn't find any test classes for ${project.name}")
|
||||||
if (testClasses.size > 0) {
|
|
||||||
add("-testclass")
|
|
||||||
add(testClasses.joinToString(","))
|
|
||||||
} else {
|
|
||||||
warn("Couldn't find any test classes for ${project.name}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,9 @@ public class JarUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val DEFAULT_JAR_EXCLUDES = arrayListOf(
|
private val DEFAULT_JAR_EXCLUDES =
|
||||||
IFileSpec.GlobSpec("META-INF/*.SF"),
|
IFileSpec.GlobSpec(arrayListOf(),
|
||||||
IFileSpec.GlobSpec("META-INF/*.DSA"),
|
arrayListOf("META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA"))
|
||||||
IFileSpec.GlobSpec("META-INF/*.RSA"))
|
|
||||||
|
|
||||||
public fun addSingleFile(directory: String, file: IncludedFile, outputStream: ZipOutputStream,
|
public fun addSingleFile(directory: String, file: IncludedFile, outputStream: ZipOutputStream,
|
||||||
expandJarFiles: Boolean, onError: (Exception) -> Unit = DEFAULT_HANDLER) {
|
expandJarFiles: Boolean, onError: (Exception) -> Unit = DEFAULT_HANDLER) {
|
||||||
|
@ -153,7 +152,7 @@ class IncludedFile(val fromOriginal: From, val toOriginal: To, val specs: List<I
|
||||||
public val from: String get() = fromOriginal.path.replace("\\", "/")
|
public val from: String get() = fromOriginal.path.replace("\\", "/")
|
||||||
public val to: String get() = toOriginal.path.replace("\\", "/")
|
public val to: String get() = toOriginal.path.replace("\\", "/")
|
||||||
override public fun toString() = toString("IncludedFile",
|
override public fun toString() = toString("IncludedFile",
|
||||||
"files", specs.map { it.toString() }.joinToString(", "),
|
"files - ", specs.map { it.toString() },
|
||||||
"from", from,
|
"from", from,
|
||||||
"to", to)
|
"to", to)
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,10 @@ import com.beust.kobalt.internal.build.BuildFile
|
||||||
import com.beust.kobalt.maven.Md5
|
import com.beust.kobalt.maven.Md5
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.file.*
|
import java.nio.file.Files
|
||||||
import kotlin.io.FileAlreadyExistsException
|
import java.nio.file.Path
|
||||||
import kotlin.io.FileSystemException
|
import java.nio.file.Paths
|
||||||
import kotlin.io.NoSuchFileException
|
import java.nio.file.StandardCopyOption
|
||||||
|
|
||||||
class KFiles {
|
class KFiles {
|
||||||
/**
|
/**
|
||||||
|
@ -277,25 +277,10 @@ class KFiles {
|
||||||
|
|
||||||
fun makeOutputTestDir(project: Project) : File = makeDir(project, KFiles.TEST_CLASSES_DIR)
|
fun makeOutputTestDir(project: Project) : File = makeDir(project, KFiles.TEST_CLASSES_DIR)
|
||||||
|
|
||||||
fun isExcluded(file: File, excludes: List<IFileSpec.GlobSpec>) = isExcluded(file.path, excludes)
|
fun isExcluded(file: File, excludes: IFileSpec.GlobSpec) = isExcluded(file.path, excludes)
|
||||||
|
|
||||||
fun isExcluded(file: String, excludes: List<IFileSpec.GlobSpec>) : Boolean {
|
|
||||||
if (excludes.isEmpty()) {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
val ex = excludes.map {
|
|
||||||
FileSystems.getDefault().getPathMatcher("glob:${it.spec}")
|
|
||||||
}
|
|
||||||
ex.forEach {
|
|
||||||
if (it.matches(Paths.get(file))) {
|
|
||||||
log(3, "Excluding $file")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
fun isExcluded(file: String, excludes: IFileSpec.GlobSpec): Boolean =
|
||||||
|
excludes.toFiles(file).isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findRecursively(directory: File, function: Function1<String, Boolean>): List<String> {
|
fun findRecursively(directory: File, function: Function1<String, Boolean>): List<String> {
|
||||||
|
|
|
@ -43,7 +43,7 @@ class PackagingPlugin @Inject constructor(val dependencyManager : DependencyMana
|
||||||
const val TASK_INSTALL: String = "install"
|
const val TASK_INSTALL: String = "install"
|
||||||
|
|
||||||
|
|
||||||
fun findIncludedFiles(directory: String, files: List<IncludedFile>, excludes: List<IFileSpec.GlobSpec>)
|
fun findIncludedFiles(directory: String, files: List<IncludedFile>, excludes: IFileSpec.GlobSpec)
|
||||||
: List<IncludedFile> {
|
: List<IncludedFile> {
|
||||||
val result = arrayListOf<IncludedFile>()
|
val result = arrayListOf<IncludedFile>()
|
||||||
files.forEach { includedFile ->
|
files.forEach { includedFile ->
|
||||||
|
@ -313,7 +313,7 @@ class PackageConfig(val project: Project) : AttributeHolder {
|
||||||
|
|
||||||
open class Zip(open var name: String? = null) {
|
open class Zip(open var name: String? = null) {
|
||||||
// internal val includes = arrayListOf<IFileSpec>()
|
// internal val includes = arrayListOf<IFileSpec>()
|
||||||
internal val excludes = arrayListOf<GlobSpec>()
|
internal val excludes = GlobSpec(arrayListOf(), arrayListOf())
|
||||||
|
|
||||||
@Directive
|
@Directive
|
||||||
public fun from(s: String) = From(s)
|
public fun from(s: String) = From(s)
|
||||||
|
@ -323,12 +323,12 @@ open class Zip(open var name: String? = null) {
|
||||||
|
|
||||||
@Directive
|
@Directive
|
||||||
public fun exclude(vararg files: String) {
|
public fun exclude(vararg files: String) {
|
||||||
files.forEach { excludes.add(GlobSpec(it)) }
|
files.forEach { excludes.excludeSpec.add(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Directive
|
@Directive
|
||||||
public fun exclude(vararg specs: GlobSpec) {
|
public fun exclude(vararg specs: GlobSpec) {
|
||||||
specs.forEach { excludes.add(it) }
|
specs.forEach { excludes.excludeSpec.addAll(it.excludeSpec) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Directive
|
@Directive
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue