diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy index a376216c8e815..388259c7a9ca4 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterConfiguration.groovy @@ -51,7 +51,7 @@ class ClusterConfiguration { FileCollection file @Override String toString() { - return "file://${file.singleFile}" + return file.singleFile.toURI().toURL().toString(); } } diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy index 72b76f0fea33d..3a06da929dd27 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/ClusterFormationTasks.groovy @@ -18,6 +18,7 @@ */ package org.elasticsearch.gradle.test +import org.apache.tools.ant.taskdefs.condition.Os import org.elasticsearch.gradle.ElasticsearchProperties import org.gradle.api.DefaultTask import org.gradle.api.GradleException @@ -76,7 +77,12 @@ class ClusterFormationTasks { for (Map.Entry command : config.setupCommands.entrySet()) { Task nextSetup = project.tasks.create(name: "${task.name}#${command.getKey()}", type: Exec, dependsOn: setup) { workingDir home - executable 'sh' + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + executable 'cmd' + args '/C', 'call' + } else { + executable 'sh' + } args command.getValue() // only show output on failure, when not in info or debug mode if (logger.isInfoEnabled() == false) { @@ -95,42 +101,56 @@ class ClusterFormationTasks { } File pidFile = pidFile(baseDir) - Task start = project.tasks.create(name: "${task.name}#start", type: Exec, dependsOn: setup) { - workingDir home - executable 'sh' - List esArgs = [ - 'bin/elasticsearch', - '-d', // daemonize! - "-Des.http.port=${config.httpPort}", - "-Des.transport.tcp.port=${config.transportPort}", - "-Des.pidfile=${pidFile}", - "-Des.path.repo=${home}/repo", - "-Des.path.shared_data=${home}/../", - ] - esArgs.addAll(config.systemProperties.collect {key, value -> "-D${key}=${value}"}) - args esArgs - errorOutput = new ByteArrayOutputStream() - doLast { - if (errorOutput.toString().isEmpty() == false) { - logger.error(errorOutput.toString()) - new File(home, 'logs' + File.separator + clusterName + '.log').eachLine { - line -> logger.error(line) + List esArgs = [ + "-Des.http.port=${config.httpPort}", + "-Des.transport.tcp.port=${config.transportPort}", + "-Des.pidfile=${pidFile}", + "-Des.path.repo=${home}/repo", + "-Des.path.shared_data=${home}/../", + ] + esArgs.addAll(config.systemProperties.collect {key, value -> "-D${key}=${value}"}) + Closure esPostStartActions = { ant, logger -> + ant.waitfor(maxwait: '30', maxwaitunit: 'second', checkevery: '500', checkeveryunit: 'millisecond', timeoutproperty: "failed${task.name}#start") { + and { + resourceexists { + file file: pidFile.toString() } - throw new GradleException('Failed to start elasticsearch') + http(url: "http://localhost:${config.httpPort}") } - ant.waitfor(maxwait: '30', maxwaitunit: 'second', checkevery: '500', checkeveryunit: 'millisecond', timeoutproperty: "failed${task.name}#start") { - and { - resourceexists { - file file: pidFile.toString() - } - http(url: "http://localhost:${config.httpPort}") - } + } + if (ant.properties.containsKey("failed${task.name}#start".toString())) { + new File(home, 'logs' + File.separator + clusterName + '.log').eachLine { + line -> logger.error(line) } - if (ant.properties.containsKey("failed${task.name}#start")) { - new File(home, 'logs' + File.separator + clusterName + '.log').eachLine { - line -> logger.error(line) + throw new GradleException('Failed to start elasticsearch') + } + } + Task start; + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + // elasticsearch.bat is spawned as it has no daemon mode + start = project.tasks.create(name: "${task.name}#start", type: DefaultTask, dependsOn: setup) << { + // Fall back to Ant exec task as Gradle Exec task does not support spawning yet + ant.exec(executable: 'cmd', spawn: true, dir: home) { + (['/C', 'call', 'bin/elasticsearch'] + esArgs).each { arg(value: it) } + } + esPostStartActions(ant, logger) + } + } else { + start = project.tasks.create(name: "${task.name}#start", type: Exec, dependsOn: setup) { + workingDir home + executable 'sh' + args 'bin/elasticsearch', '-d' // daemonize! + args esArgs + errorOutput = new ByteArrayOutputStream() + doLast { + if (errorOutput.toString().isEmpty() == false) { + logger.error(errorOutput.toString()) + new File(home, 'logs' + File.separator + clusterName + '.log').eachLine { + line -> logger.error(line) + } + throw new GradleException('Failed to start elasticsearch') } - throw new GradleException('Failed to start elasticsearch') + esPostStartActions(ant, logger) } } } @@ -140,8 +160,13 @@ class ClusterFormationTasks { static void addNodeStopTask(Project project, Task task, File baseDir) { LazyPidReader pidFile = new LazyPidReader(pidFile: pidFile(baseDir)) Task stop = project.tasks.create(name: task.name + '#stop', type: Exec) { - executable 'kill' - args '-9', pidFile + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + executable 'Taskkill' + args '/PID', pidFile, '/F' + } else { + executable 'kill' + args '-9', pidFile + } doLast { // TODO: wait for pid to close, or kill -9 and fail } diff --git a/test-framework/build.gradle b/test-framework/build.gradle index 8496b6c83d72e..499985fa889b6 100644 --- a/test-framework/build.gradle +++ b/test-framework/build.gradle @@ -28,70 +28,41 @@ project.ext { srcDir = new File(project.buildDir, 'src') coreDir = new File(project("${projectsPrefix}:core").projectDir, 'src' + File.separator + 'test') } -class ExecHack extends DefaultTask { - File srcDir = project.ext.srcDir - File coreDir = project.ext.coreDir - List commands = ["rm -rf ${srcDir}", "mkdir -p ${srcDir}"] - void copy(String path) { - File corePath = project.file("${coreDir}/${path}") - File srcPath = project.file("${srcDir}/${path}") - String dir = path - if (corePath.isDirectory()) { - srcPath = srcPath.getParentFile() - } else { - dir = coreDir.toURI().relativize(corePath.getParentFile().toURI()).getPath() - } - commands.add("mkdir -p ${srcDir}/${dir}") - commands.add("cp -a ${corePath} ${srcPath}") - } - void remove(String path) { - commands.add("rm -rf ${srcDir}/${path}") - } - @TaskAction - void executeHack() { - for (String command : commands) { - logger.info(command) - def p = command.execute() - p.waitFor() - if (p.exitValue()) { - logger.error(p.text) - throw new GradleException("Failed to execute '${command}'") - } - } - } -} sourceSets.main.java.srcDir(new File(srcDir, "java")) sourceSets.main.resources.srcDir(new File(srcDir, "resources")) -task copySourceFiles(type: ExecHack) { - copy 'resources/log4j.properties' - copy 'java/org/elasticsearch/test' - copy 'java/org/elasticsearch/bootstrap/BootstrapForTesting.java' - copy 'java/org/elasticsearch/bootstrap/MockPluginPolicy.java' - copy 'java/org/elasticsearch/common/cli/CliToolTestCase.java' - copy 'java/org/elasticsearch/cluster/MockInternalClusterInfoService.java' - copy 'java/org/elasticsearch/index/MockEngineFactoryPlugin.java' - copy 'java/org/elasticsearch/search/MockSearchService.java' - copy 'java/org/elasticsearch/search/aggregations/bucket/AbstractTermsTestCase.java' - copy 'java/org/elasticsearch/search/aggregations/bucket/script/NativeSignificanceScoreScriptNoParams.java' - copy 'java/org/elasticsearch/search/aggregations/bucket/script/NativeSignificanceScoreScriptWithParams.java' - copy 'java/org/elasticsearch/search/aggregations/bucket/script/TestScript.java' - copy 'java/org/elasticsearch/search/aggregations/metrics/AbstractNumericTestCase.java' - copy 'java/org/elasticsearch/percolator/PercolatorTestUtil.java' - copy 'java/org/elasticsearch/cache/recycler/MockPageCacheRecycler.java' - copy 'java/org/elasticsearch/common/util/MockBigArrays.java' - copy 'java/org/elasticsearch/node/NodeMocksPlugin.java' - copy 'java/org/elasticsearch/node/MockNode.java' - copy 'java/org/elasticsearch/common/io/PathUtilsForTesting.java' - // unit tests for yaml suite parser & rest spec parser need to be excluded - remove 'java/org/elasticsearch/test/rest/test' - // unit tests for test framework classes - remove 'java/org/elasticsearch/test/test' +task copySourceFiles(type: Sync) { + from(coreDir) { + include 'resources/log4j.properties' + include 'java/org/elasticsearch/test/**' + include 'java/org/elasticsearch/bootstrap/BootstrapForTesting.java' + include 'java/org/elasticsearch/bootstrap/MockPluginPolicy.java' + include 'java/org/elasticsearch/common/cli/CliToolTestCase.java' + include 'java/org/elasticsearch/cluster/MockInternalClusterInfoService.java' + include 'java/org/elasticsearch/index/MockEngineFactoryPlugin.java' + include 'java/org/elasticsearch/search/MockSearchService.java' + include 'java/org/elasticsearch/search/aggregations/bucket/AbstractTermsTestCase.java' + include 'java/org/elasticsearch/search/aggregations/bucket/script/NativeSignificanceScoreScriptNoParams.java' + include 'java/org/elasticsearch/search/aggregations/bucket/script/NativeSignificanceScoreScriptWithParams.java' + include 'java/org/elasticsearch/search/aggregations/bucket/script/TestScript.java' + include 'java/org/elasticsearch/search/aggregations/metrics/AbstractNumericTestCase.java' + include 'java/org/elasticsearch/percolator/PercolatorTestUtil.java' + include 'java/org/elasticsearch/cache/recycler/MockPageCacheRecycler.java' + include 'java/org/elasticsearch/common/util/MockBigArrays.java' + include 'java/org/elasticsearch/node/NodeMocksPlugin.java' + include 'java/org/elasticsearch/node/MockNode.java' + include 'java/org/elasticsearch/common/io/PathUtilsForTesting.java' + // unit tests for yaml suite parser & rest spec parser need to be excluded + exclude 'java/org/elasticsearch/test/rest/test/**' + // unit tests for test framework classes + exclude 'java/org/elasticsearch/test/test/**' - // no geo (requires optional deps) - remove 'java/org/elasticsearch/test/hamcrest/ElasticsearchGeoAssertions.java' - remove 'java/org/elasticsearch/test/geo/RandomShapeGenerator.java' - // this mock is just for a single logging test - remove 'java/org/elasticsearch/test/MockLogAppender.java' + // no geo (requires optional deps) + exclude 'java/org/elasticsearch/test/hamcrest/ElasticsearchGeoAssertions.java' + exclude 'java/org/elasticsearch/test/geo/RandomShapeGenerator.java' + // this mock is just for a single logging test + exclude 'java/org/elasticsearch/test/MockLogAppender.java' + } + into srcDir } compileJava.dependsOn copySourceFiles