import org.python.util.PythonInterpreter import org.python.core.* buildscript { repositories { mavenLocal() mavenCentral() } dependencies { classpath group: 'org.python', name: 'jython-standalone', version: '2.7.1b2' } } subprojects { apply plugin: 'java' sourceCompatibility = '1.8' targetCompatibility = '1.8' repositories { mavenLocal() mavenCentral() } sourceSets { main { java { srcDir projectDir } } } List tasks = [] projectDir.eachFileRecurse { if (it.name.endsWith('.java')) { List lines = it.readLines() Boolean hasMainMethod = lines.join('').contains('main(String[] args)') Boolean hasMainParam = lines.find { it.startsWith('// {main: ')} Boolean willNotCompile = lines.find { it.startsWith('// {CompileTimeError') } Boolean validateByHand = lines.find { it.startsWith('// {ValidateByHand}') } Boolean throwsException = lines.find { it.startsWith('// {ThrowsException}') } // add tasks for java sources with main methods if ((hasMainMethod || hasMainParam) && (!willNotCompile)) { String maybeArgsLine = lines.find { it.startsWith('// {Args: ')} List maybeArgs = [] if (maybeArgsLine != null) { maybeArgs = maybeArgsLine.trim().replaceAll('\\/\\/ \\{Args: ', '').reverse().replaceFirst('}', '').reverse().split(' ') } String mainClass = it.name.replaceAll('.java', '') String taskName = mainClass if (!validateByHand) { // only add tasks that we know we can run successfully to the task list tasks.add(taskName) } // some java sources with a main method specify a different main class String maybeMainLine = lines.find { it.startsWith('// {main: ')} if (maybeMainLine != null) { mainClass = maybeMainLine.trim().replaceAll('\\/\\/ \\{main: ', '').replaceAll('}', '') } // some java sources with JVM args List maybeJvmArgs = [] String maybeJvmArgsLine = lines.find { it.startsWith('// {JVMArgs: ')} if (maybeJvmArgsLine != null) { maybeJvmArgs = maybeJvmArgsLine.trim().replaceAll('\\/\\/ \\{JVMArgs: ', '').replaceAll('}', '').split(' ') } // some java sources depend on others to be run first String maybeRunFirst = null String maybeRunFirstLine = lines.find { it.startsWith('// {RunFirst: ')} if (maybeRunFirstLine != null) { maybeRunFirst = maybeRunFirstLine.trim().replaceAll('\\/\\/ \\{RunFirst: ', '').replaceAll('}', '') } // some java apps intentionally throw an exception Boolean maybeIgnoreExitValue = (validateByHand || throwsException) // some java apps need a timeout Boolean timeOutDuringTesting = false if (lines.find { it.startsWith('// {TimeOutDuringTesting}') } != null) { timeOutDuringTesting = true } // create run and test tasks if (timeOutDuringTesting) { // todo: apps with timeOutDuringTesting need special handling task "$taskName" << { println "not implemented" } task "test$taskName" << { println "not implemented" } } else { task "$taskName"(type: JavaExec, dependsOn: maybeRunFirst) { main = mainClass classpath = sourceSets.main.runtimeClasspath args = maybeArgs jvmArgs = maybeJvmArgs ignoreExitValue = maybeIgnoreExitValue } Integer expectedOutputStartLine = lines.findIndexOf { it.startsWith('/* Output:') } Integer expectedOutputEndLine = -1 List expectedOutputLines = [] if (expectedOutputStartLine != -1) { expectedOutputStartLine += 1 expectedOutputEndLine = lines.findIndexOf(expectedOutputStartLine, { it.startsWith('*/') }) if (expectedOutputEndLine == -1) { expectedOutputEndLine = expectedOutputStartLine } expectedOutputLines = lines.subList(expectedOutputStartLine, expectedOutputEndLine) } OutputStream testStandardOutput = new ByteArrayOutputStream() OutputStream testErrorOutput = new ByteArrayOutputStream() task "test$taskName"(type: JavaExec, dependsOn: maybeRunFirst) { main = mainClass classpath = sourceSets.main.runtimeClasspath args = maybeArgs jvmArgs = maybeJvmArgs ignoreExitValue = maybeIgnoreExitValue standardOutput = testStandardOutput errorOutput = testErrorOutput doLast { // test the output here def rstrip = { it.replaceAll('\\s$', '') } def textwrap = { String text -> if (text.length() > 0) { PythonInterpreter interpreter = new PythonInterpreter() interpreter.exec("from textwrap import fill") PyFunction textwrapFill = (PyFunction) interpreter.get("fill") PyObject result = textwrapFill.__call__(new PyString(text), new PyInteger(59)) return ((String) result.__tojava__(String.class)).readLines() } else { return [""] } } List testStandardOutputLines = testStandardOutput.toString().readLines().collect(rstrip).collectMany(textwrap) assert expectedOutputLines.size() == testStandardOutputLines.size() expectedOutputLines.eachWithIndex { expectedLine, i -> assert expectedLine == testStandardOutputLines.get(i) } } } } } // exclude java sources that will not compile if (willNotCompile) { sourceSets.main.java.excludes.add(it.name) } } } task run(dependsOn: tasks) List testTasks = tasks.collect { "test" + it } task test(overwrite:true, dependsOn: testTasks) } configure(subprojects - project(':onjava')) { dependencies { compile project(':onjava') } }