1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-26 08:27:12 -07:00

Made test runners into contributors.

This commit is contained in:
Cedric Beust 2015-11-28 06:51:00 -08:00
parent 6630f55197
commit b700e94b5f
13 changed files with 125 additions and 63 deletions

View file

@ -1,9 +1,10 @@
package com.beust.kobalt.api
import com.beust.kobalt.TaskResult
import com.beust.kobalt.maven.IClasspathDependency
/**
* Plugins that can run a project (task "run") should implement this interface.
* Plugins that can run a project (task "run" or "test") should implement this interface.
*/
interface IRunnerContributor : IContributor {
companion object {
@ -23,7 +24,7 @@ interface IRunnerContributor : IContributor {
/**
* Run the project.
*/
fun run(project: Project, context: KobaltContext) : TaskResult
fun run(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>) : TaskResult
}

View file

@ -2,6 +2,9 @@ package com.beust.kobalt.internal
import com.beust.kobalt.JavaInfo
import com.beust.kobalt.SystemProperties
import com.beust.kobalt.TaskResult
import com.beust.kobalt.api.IRunnerContributor
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.maven.IClasspathDependency
import com.beust.kobalt.misc.KFiles
@ -9,11 +12,15 @@ import com.beust.kobalt.misc.log
import java.io.File
import java.net.URLClassLoader
abstract class GenericTestRunner(open val project: Project, open val classpath: List<IClasspathDependency>) {
abstract class GenericTestRunner : IRunnerContributor {
abstract val mainClass: String
abstract val args: List<String>
abstract fun args(project: Project, classpath: List<IClasspathDependency>) : List<String>
protected fun findTestClasses(): List<String> {
override fun run(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>)
= TaskResult(runTests(project, context, classpath))
protected fun findTestClasses(project: Project, classpath: List<IClasspathDependency>): List<String> {
val path = KFiles.joinDir(project.directory, project.buildDirectory, KFiles.TEST_CLASSES_DIR)
val result = KFiles.findRecursively(File(path), arrayListOf(File(".")), {
file -> file.endsWith(".class")
@ -39,9 +46,10 @@ abstract class GenericTestRunner(open val project: Project, open val classpath:
/**
* @return true if all the tests passed
*/
fun runTests() : Boolean {
fun runTests(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>) : Boolean {
val jvm = JavaInfo.create(File(SystemProperties.javaBase))
val java = jvm.javaExecutable
val args = args(project, classpath)
if (args.size > 0) {
val allArgs = arrayListOf<String>().apply {
add(java!!.absolutePath)

View file

@ -1,12 +1,19 @@
package com.beust.kobalt.internal
import com.beust.kobalt.api.IRunnerContributor
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.maven.IClasspathDependency
public class JUnitRunner(override val project: Project, override val classpath: List<IClasspathDependency>)
: GenericTestRunner(project, classpath) {
public class JUnitRunner() : GenericTestRunner() {
override val mainClass = "org.junit.runner.JUnitCore"
override val args = findTestClasses()
override fun runAffinity(project: Project, context: KobaltContext) =
if (project.testDependencies.any { it.id.contains("junit")}) IRunnerContributor.DEFAULT_POSITIVE_AFFINITY
else 0
override fun args(project: Project, classpath: List<IClasspathDependency>) = findTestClasses(project, classpath)
}

View file

@ -7,7 +7,9 @@ import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.api.annotation.ExportedProjectProperty
import com.beust.kobalt.api.annotation.Task
import com.beust.kobalt.maven.*
import com.beust.kobalt.maven.DepFactory
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.LocalRepo
import com.beust.kobalt.misc.KFiles
import com.beust.kobalt.misc.KobaltExecutors
import com.beust.kobalt.misc.log
@ -55,33 +57,18 @@ abstract class JvmCompilerPlugin @Inject constructor(
addVariantTasks(project, "compile", runTask = { taskCompile(project) })
}
/**
* @return the test dependencies for this project, including the contributors.
*/
protected fun testDependencies(project: Project) : List<IClasspathDependency> {
val result = arrayListOf<IClasspathDependency>()
result.add(FileDependency(makeOutputDir(project).absolutePath))
result.add(FileDependency(makeOutputTestDir(project).absolutePath))
with(project) {
arrayListOf(compileDependencies, compileProvidedDependencies, testDependencies,
testProvidedDependencies).forEach {
result.addAll(dependencyManager.calculateDependencies(project, context, projects(), it))
}
}
val result2 = dependencyManager.reorderDependencies(result)
return result2
}
@Task(name = TASK_TEST, description = "Run the tests", runAfter = arrayOf("compile", "compileTest"))
fun taskTest(project: Project) : TaskResult {
lp(project, "Running tests")
val success =
if (project.testDependencies.any { it.id.contains("testng")} ) {
TestNgRunner(project, testDependencies(project)).runTests()
} else {
JUnitRunner(project, testDependencies(project)).runTests()
}
return TaskResult(success)
val runContributor = context.pluginInfo.testRunnerContributors.maxBy { it.runAffinity(project, context)}
if (runContributor != null && runContributor.runAffinity(project, context) > 0) {
return runContributor.run(project, context, dependencyManager.testDependencies(project, context,
projects()))
} else {
log(2, "Couldn't find a test runner for project ${project.name}, not running any tests")
return TaskResult()
}
}
@Task(name = TASK_CLEAN, description = "Clean the project", runBefore = arrayOf("compile"))
@ -94,14 +81,6 @@ abstract class JvmCompilerPlugin @Inject constructor(
return TaskResult()
}
protected fun makeOutputDir(project: Project) : File = makeDir(project, KFiles.CLASSES_DIR)
protected fun makeOutputTestDir(project: Project) : File = makeDir(project, KFiles.TEST_CLASSES_DIR)
private fun makeDir(project: Project, suffix: String) : File {
return File(project.directory, project.buildDirectory + File.separator + suffix).apply { mkdirs() }
}
/**
* Copy the resources from a source directory to the build one
*/
@ -120,7 +99,7 @@ abstract class JvmCompilerPlugin @Inject constructor(
if (sourceDirs.size > 0) {
lp(project, "Copying $sourceSet resources")
val absOutputDir = File(KFiles.joinDir(project.directory, project.buildDirectory!!, outputDir))
val absOutputDir = File(KFiles.joinDir(project.directory, project.buildDirectory, outputDir))
sourceDirs.map { File(project.directory, it) }.filter {
it.exists()
} .forEach {

View file

@ -62,8 +62,11 @@ class KobaltPluginXml {
@XmlElement(name = "build-directory-interceptors") @JvmField
var buildDirectoryInterceptors: ClassNameXml? = null
@XmlElement(name = "run-contributors") @JvmField
var runContributors: ClassNameXml? = null
@XmlElement(name = "runner-contributors") @JvmField
var runnerContributors: ClassNameXml? = null
@XmlElement(name = "test-runner-contributors") @JvmField
var testRunnerContributors: ClassNameXml? = null
}
class ContributorXml {
@ -91,7 +94,8 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) {
val compilerInterceptors = arrayListOf<ICompilerInterceptor>()
val sourceDirectoriesInterceptors = arrayListOf<ISourceDirectoriesIncerceptor>()
val buildDirectoryInterceptors = arrayListOf<IBuildDirectoryIncerceptor>()
val runContributors = arrayListOf<IRunnerContributor>()
val runnerContributors = arrayListOf<IRunnerContributor>()
val testRunnerContributors = arrayListOf<IRunnerContributor>()
// Future contributors:
// source files
@ -165,8 +169,11 @@ class PluginInfo(val xml: KobaltPluginXml, val classLoader: ClassLoader?) {
xml.buildDirectoryInterceptors?.className?.forEach {
buildDirectoryInterceptors.add(factory.instanceOf(forName(it)) as IBuildDirectoryIncerceptor)
}
xml.runContributors?.className?.forEach {
runContributors.add(factory.instanceOf(forName(it)) as IRunnerContributor)
xml.runnerContributors?.className?.forEach {
runnerContributors.add(factory.instanceOf(forName(it)) as IRunnerContributor)
}
xml.testRunnerContributors?.className?.forEach {
testRunnerContributors.add(factory.instanceOf(forName(it)) as IRunnerContributor)
}
}

View file

@ -1,16 +1,21 @@
package com.beust.kobalt.internal
import com.beust.kobalt.api.IRunnerContributor
import com.beust.kobalt.api.KobaltContext
import com.beust.kobalt.api.Project
import com.beust.kobalt.maven.IClasspathDependency
import com.beust.kobalt.misc.KFiles
import java.io.File
public class TestNgRunner(override val project: Project, override val classpath: List<IClasspathDependency>)
: GenericTestRunner(project, classpath) {
public class TestNgRunner() : GenericTestRunner() {
override val mainClass = "org.testng.TestNG"
override val args: List<String>
get() = arrayListOf<String>().apply {
override fun runAffinity(project: Project, context: KobaltContext) =
if (project.testDependencies.any { it.id.contains("testng")}) IRunnerContributor.DEFAULT_POSITIVE_AFFINITY
else 0
override fun args(project: Project, classpath: List<IClasspathDependency>) = arrayListOf<String>().apply {
if (project.testArgs.size > 0) {
addAll(project.testArgs)
} else {
@ -19,7 +24,7 @@ public class TestNgRunner(override val project: Project, override val classpath:
add(testngXml.absolutePath)
} else {
add("-testclass")
addAll(findTestClasses())
addAll(findTestClasses(project, classpath))
}
}
}

View file

@ -114,4 +114,42 @@ public class DependencyManager @Inject constructor(val executors: KobaltExecutor
return result
}
/**
* @return the test dependencies for this project, including the contributors.
*/
fun dependencies(project: Project, context: KobaltContext,
projects: List<ProjectDescription>) : List<IClasspathDependency> {
val result = arrayListOf<IClasspathDependency>()
result.add(FileDependency(KFiles.makeOutputDir(project).absolutePath))
result.add(FileDependency(KFiles.makeOutputTestDir(project).absolutePath))
with(project) {
arrayListOf(compileDependencies, compileProvidedDependencies).forEach {
result.addAll(calculateDependencies(project, context, projects, it))
}
}
val result2 = reorderDependencies(result)
return result2
}
/**
* @return the test dependencies for this project, including the contributors.
*/
fun testDependencies(project: Project, context: KobaltContext,
projects: List<ProjectDescription>) : List<IClasspathDependency> {
val result = arrayListOf<IClasspathDependency>()
result.add(FileDependency(KFiles.makeOutputDir(project).absolutePath))
result.add(FileDependency(KFiles.makeOutputTestDir(project).absolutePath))
with(project) {
arrayListOf(compileDependencies, compileProvidedDependencies, testDependencies,
testProvidedDependencies).forEach {
result.addAll(calculateDependencies(project, context, projects, it))
}
}
val result2 = reorderDependencies(result)
return result2
}
}

View file

@ -2,6 +2,7 @@ package com.beust.kobalt.misc
import com.beust.kobalt.SystemProperties
import com.beust.kobalt.api.Kobalt
import com.beust.kobalt.api.Project
import com.beust.kobalt.homeDir
import com.beust.kobalt.internal.build.BuildFile
import java.io.File
@ -239,6 +240,14 @@ class KFiles {
}
fun src(filePath: String): String = KFiles.joinDir(KOBALT_DIR, SRC, filePath)
fun makeDir(project: Project, suffix: String) : File {
return File(project.directory, project.buildDirectory + File.separator + suffix).apply { mkdirs() }
}
fun makeOutputDir(project: Project) : File = makeDir(project, KFiles.CLASSES_DIR)
fun makeOutputTestDir(project: Project) : File = makeDir(project, KFiles.TEST_CLASSES_DIR)
}
fun findRecursively(directory: File, function: Function1<String, Boolean>): List<String> {

View file

@ -397,7 +397,7 @@ public class AndroidPlugin @Inject constructor(val javaCompiler: JavaCompiler, v
return if (File(manifest).exists()) IRunnerContributor.DEFAULT_POSITIVE_AFFINITY else 0
}
override fun run(project: Project, context: KobaltContext): TaskResult {
override fun run(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>): TaskResult {
val manifest = AndroidFiles.manifest(project, context)
FileInputStream(File(manifest)).use { ins ->
// adb shell am start -n com.package.name/com.package.name.ActivityName

View file

@ -6,6 +6,7 @@ import com.beust.kobalt.api.annotation.Directive
import com.beust.kobalt.api.annotation.Task
import com.beust.kobalt.internal.JvmCompilerPlugin
import com.beust.kobalt.maven.DependencyManager
import com.beust.kobalt.maven.IClasspathDependency
import com.beust.kobalt.misc.KobaltExecutors
import com.beust.kobalt.misc.RunCommand
import com.beust.kobalt.misc.warn
@ -48,15 +49,17 @@ class ApplicationPlugin @Inject constructor(val executors: KobaltExecutors,
@Task(name = "run", description = "Run the main class", runAfter = arrayOf("install"))
fun taskRun(project: Project): TaskResult {
val runContributor = context.pluginInfo.runContributors.maxBy { it.runAffinity(project, context)}
val runContributor = context.pluginInfo.runnerContributors.maxBy { it.runAffinity(project, context)}
if (runContributor != null && runContributor.runAffinity(project, context) > 0) {
return runContributor.run(project, context)
return runContributor.run(project, context, dependencyManager.dependencies(project, context, projects()))
} else {
warn("Couldn't find a runner for project ${project.name}")
return TaskResult()
}
}
private fun projects() = context.pluginInfo.projectContributors.flatMap { it.projects() }
private fun isFatJar(packages: List<PackageConfig>, jarName: String): Boolean {
packages.forEach { pc ->
pc.jars.forEach { jar ->
@ -74,7 +77,7 @@ class ApplicationPlugin @Inject constructor(val executors: KobaltExecutors,
return if (configurationFor(project) != null) IRunnerContributor.DEFAULT_POSITIVE_AFFINITY else 0
}
override fun run(project: Project, context: KobaltContext): TaskResult {
override fun run(project: Project, context: KobaltContext, classpath: List<IClasspathDependency>): TaskResult {
var result = TaskResult()
configurationFor(project)?.let { config ->
if (config.mainClass != null) {

View file

@ -81,8 +81,9 @@ class JavaPlugin @Inject constructor(
val result =
if (sourceFiles.size > 0) {
copyResources(project, JvmCompilerPlugin.SOURCE_SET_TEST)
val buildDir = makeOutputTestDir(project)
javaCompiler.compile(project, context, CompilerActionInfo(project.directory, testDependencies(project),
val buildDir = KFiles.makeOutputTestDir(project)
javaCompiler.compile(project, context, CompilerActionInfo(project.directory,
dependencyManager.testDependencies(project, context, projects()),
sourceFiles, buildDir, compilerArgsFor(project)))
} else {
warn("Couldn't find any tests to compile")

View file

@ -69,9 +69,9 @@ class KotlinPlugin @Inject constructor(
val result =
if (sourceFiles.size > 0) {
compilePrivate(project, testDependencies(project),
compilePrivate(project, dependencyManager.testDependencies(project, context, projects()),
sourceFiles,
makeOutputTestDir(project))
KFiles.makeOutputTestDir(project))
} else {
warn("Couldn't find any test files")
TaskResult()

View file

@ -37,8 +37,12 @@
<compiler-interceptors>
<class-name>com.beust.kobalt.plugin.android.AndroidPlugin</class-name>
</compiler-interceptors>
<run-contributors>
<runner-contributors>
<class-name>com.beust.kobalt.plugin.application.ApplicationPlugin</class-name>
<class-name>com.beust.kobalt.plugin.android.AndroidPlugin</class-name>
</run-contributors>
</runner-contributors>
<test-runner-contributors>
<class-name>com.beust.kobalt.internal.JUnitRunner</class-name>
<class-name>com.beust.kobalt.internal.TestNgRunner</class-name>
</test-runner-contributors>
</kobalt-plugin>