diff --git a/benchmarks/build.gradle b/benchmarks/build.gradle index 13eca8f06c26f..351b0b9e97118 100644 --- a/benchmarks/build.gradle +++ b/benchmarks/build.gradle @@ -24,7 +24,7 @@ mainClassName = 'org.openjdk.jmh.Main' assemble.enabled = false archivesBaseName = 'elasticsearch-benchmarks' -test.enabled = false +unitTest.enabled = false dependencies { compile("org.elasticsearch:elasticsearch:${version}") { diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index ba512708e1977..9d25532d4cef1 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -199,14 +199,15 @@ if (project != rootProject) { into localDownloads } - test { + unitTest { // The test task is configured to runtimeJava version, but build-tools doesn't support all of them, so test // with compiler instead on the ones that are too old. if (project.runtimeJavaVersion <= JavaVersion.VERSION_1_10) { - executable = "${project.compilerJavaHome}/bin/java" + jvm = "${project.compilerJavaHome}/bin/java" } } - + + // This can't be an RandomizedTestingTask because we can't yet reference it task integTest(type: Test) { // integration test requires the local testing repo for example plugin builds dependsOn project.rootProject.allprojects.collect { @@ -214,6 +215,8 @@ if (project != rootProject) { } dependsOn setupLocalDownloads exclude "**/*Tests.class" + testClassesDirs = sourceSets.test.output.classesDirs + classpath = sourceSets.test.runtimeClasspath inputs.dir(file("src/testKit")) // tell BuildExamplePluginsIT where to find the example plugins systemProperty ( @@ -229,7 +232,11 @@ if (project != rootProject) { if (isLuceneSnapshot) { systemProperty 'test.lucene-snapshot-revision', isLuceneSnapshot[0][1] } - maxParallelForks System.getProperty('tests.jvms', project.rootProject.ext.defaultParallel.toString()) as Integer + String defaultParallel = System.getProperty('tests.jvms', project.rootProject.ext.defaultParallel) + if (defaultParallel == "auto") { + defaultParallel = Math.max(Runtime.getRuntime().availableProcessors(), 4) + } + maxParallelForks defaultParallel as Integer } check.dependsOn(integTest) diff --git a/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/BalancersConfiguration.groovy b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/BalancersConfiguration.groovy new file mode 100644 index 0000000000000..91355bf2494cd --- /dev/null +++ b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/BalancersConfiguration.groovy @@ -0,0 +1,53 @@ +package com.carrotsearch.gradle.junit4 + +import com.carrotsearch.ant.tasks.junit4.SuiteBalancer +import com.carrotsearch.ant.tasks.junit4.balancers.ExecutionTimeBalancer +import com.carrotsearch.ant.tasks.junit4.listeners.ExecutionTimesReport +import org.apache.tools.ant.types.FileSet + +class BalancersConfiguration { + // parent task, so executionTime can register an additional listener + RandomizedTestingTask task + List balancers = new ArrayList<>() + + void executionTime(Map properties) { + ExecutionTimeBalancer balancer = new ExecutionTimeBalancer() + + FileSet fileSet = new FileSet() + Object filename = properties.remove('cacheFilename') + if (filename == null) { + throw new IllegalArgumentException('cacheFilename is required for executionTime balancer') + } + fileSet.setIncludes(filename.toString()) + + File cacheDir = task.project.projectDir + Object dir = properties.remove('cacheDir') + if (dir != null) { + cacheDir = new File(dir.toString()) + } + fileSet.setDir(cacheDir) + balancer.add(fileSet) + + int historySize = 10 + Object size = properties.remove('historySize') + if (size instanceof Integer) { + historySize = (Integer)size + } else if (size != null) { + throw new IllegalArgumentException('historySize must be an integer') + } + ExecutionTimesReport listener = new ExecutionTimesReport() + listener.setFile(new File(cacheDir, filename.toString())) + listener.setHistoryLength(historySize) + + if (properties.isEmpty() == false) { + throw new IllegalArgumentException('Unknown properties for executionTime balancer: ' + properties.keySet()) + } + + task.listenersConfig.listeners.add(listener) + balancers.add(balancer) + } + + void custom(SuiteBalancer balancer) { + balancers.add(balancer) + } +} diff --git a/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/ListenersConfiguration.groovy b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/ListenersConfiguration.groovy new file mode 100644 index 0000000000000..5fa5baa8ffb0c --- /dev/null +++ b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/ListenersConfiguration.groovy @@ -0,0 +1,25 @@ +package com.carrotsearch.gradle.junit4 + +import com.carrotsearch.ant.tasks.junit4.listeners.AggregatedEventListener +import com.carrotsearch.ant.tasks.junit4.listeners.antxml.AntXmlReport + + +class ListenersConfiguration { + RandomizedTestingTask task + List listeners = new ArrayList<>() + + void junitReport(Map props) { + AntXmlReport reportListener = new AntXmlReport() + Object dir = props == null ? null : props.get('dir') + if (dir != null) { + reportListener.setDir(task.project.file(dir)) + } else { + reportListener.setDir(new File(task.project.buildDir, 'reports' + File.separator + "${task.name}Junit")) + } + listeners.add(reportListener) + } + + void custom(AggregatedEventListener listener) { + listeners.add(listener) + } +} diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/LoggingOutputStream.groovy b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/LoggingOutputStream.groovy similarity index 97% rename from buildSrc/src/main/groovy/org/elasticsearch/gradle/LoggingOutputStream.groovy rename to buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/LoggingOutputStream.groovy index e2e2b7c954482..ce0995a5a8c70 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/LoggingOutputStream.groovy +++ b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/LoggingOutputStream.groovy @@ -1,4 +1,4 @@ -package org.elasticsearch.gradle +package com.carrotsearch.gradle.junit4 import org.gradle.api.logging.LogLevel import org.gradle.api.logging.Logger diff --git a/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/RandomizedTestingPlugin.groovy b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/RandomizedTestingPlugin.groovy new file mode 100644 index 0000000000000..7d554386c3920 --- /dev/null +++ b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/RandomizedTestingPlugin.groovy @@ -0,0 +1,60 @@ +package com.carrotsearch.gradle.junit4 + +import com.carrotsearch.ant.tasks.junit4.JUnit4 +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.tasks.TaskContainer + +class RandomizedTestingPlugin implements Plugin { + + void apply(Project project) { + String seed = setupSeed(project) + createUnitTestTask(project.tasks) + configureAnt(project.ant, seed) + } + + /** + * Pins the test seed at configuration time so it isn't different on every + * {@link RandomizedTestingTask} execution. This is useful if random + * decisions in one run of {@linkplain RandomizedTestingTask} influence the + * outcome of subsequent runs. Pinning the seed up front like this makes + * the reproduction line from one run be useful on another run. + */ + static String setupSeed(Project project) { + if (project.rootProject.ext.has('testSeed')) { + /* Skip this if we've already pinned the testSeed. It is important + * that this checks the rootProject so that we know we've only ever + * initialized one time. */ + return project.rootProject.ext.testSeed + } + String testSeed = System.getProperty('tests.seed') + if (testSeed == null) { + long seed = new Random(System.currentTimeMillis()).nextLong() + testSeed = Long.toUnsignedString(seed, 16).toUpperCase(Locale.ROOT) + } + /* Set the testSeed on the root project first so other projects can use + * it during initialization. */ + project.rootProject.ext.testSeed = testSeed + project.rootProject.subprojects { + project.ext.testSeed = testSeed + } + + return testSeed + } + + static void createUnitTestTask(TaskContainer tasks) { + // only create a unitTest task if the `test` task exists as some project don't make use of it. + tasks.matching { it.name == "test" }.all { + // We don't want to run any tests with the Gradle test runner since we add our own randomized runner + it.enabled = false + RandomizedTestingTask unitTest = tasks.create('unitTest', RandomizedTestingTask) + unitTest.description = 'Runs unit tests with the randomized testing framework' + it.dependsOn unitTest + } + } + + static void configureAnt(AntBuilder ant, String seed) { + ant.project.addTaskDefinition('junit4:junit4', JUnit4.class) + ant.properties.put('tests.seed', seed) + } +} diff --git a/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/RandomizedTestingTask.groovy b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/RandomizedTestingTask.groovy new file mode 100644 index 0000000000000..e5500d60093ed --- /dev/null +++ b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/RandomizedTestingTask.groovy @@ -0,0 +1,330 @@ +package com.carrotsearch.gradle.junit4 + +import com.carrotsearch.ant.tasks.junit4.ListenersList +import com.carrotsearch.ant.tasks.junit4.listeners.AggregatedEventListener +import groovy.xml.NamespaceBuilder +import groovy.xml.NamespaceBuilderSupport +import org.apache.tools.ant.BuildException +import org.apache.tools.ant.DefaultLogger +import org.apache.tools.ant.Project +import org.apache.tools.ant.RuntimeConfigurable +import org.apache.tools.ant.UnknownElement +import org.elasticsearch.gradle.BuildPlugin +import org.gradle.api.DefaultTask +import org.gradle.api.InvalidUserDataException +import org.gradle.api.file.FileCollection +import org.gradle.api.file.FileTreeElement +import org.gradle.api.specs.Spec +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputDirectory +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.options.Option +import org.gradle.api.tasks.util.PatternFilterable +import org.gradle.api.tasks.util.PatternSet +import org.gradle.internal.logging.progress.ProgressLoggerFactory +import org.gradle.util.ConfigureUtil + +import javax.inject.Inject + +class RandomizedTestingTask extends DefaultTask { + + // TODO: change to "executable" to match gradle test params? + @Optional + @Input + String jvm = 'java' + + @Optional + @Input + File workingDir = new File(project.buildDir, 'testrun' + File.separator + name) + + @Optional + @Input + FileCollection classpath + + @Input + String parallelism = '1' + + @Input + FileCollection testClassesDirs + + @Optional + @Input + boolean haltOnFailure = true + + @Optional + @Input + boolean shuffleOnSlave = true + + @Optional + @Input + boolean enableAssertions = true + + @Optional + @Input + boolean enableSystemAssertions = true + + @Optional + @Input + boolean leaveTemporary = false + + @Optional + @Input + String ifNoTests = 'ignore' + + @Optional + @Input + String onNonEmptyWorkDirectory = 'fail' + + TestLoggingConfiguration testLoggingConfig = new TestLoggingConfiguration() + + BalancersConfiguration balancersConfig = new BalancersConfiguration(task: this) + ListenersConfiguration listenersConfig = new ListenersConfiguration(task: this) + + List jvmArgs = new ArrayList<>() + + @Optional + @Input + String argLine = null + + Map systemProperties = new HashMap<>() + Map environmentVariables = new HashMap<>() + PatternFilterable patternSet = new PatternSet() + + RandomizedTestingTask() { + outputs.upToDateWhen {false} // randomized tests are never up to date + listenersConfig.listeners.add(new TestProgressLogger(factory: getProgressLoggerFactory())) + listenersConfig.listeners.add(new TestReportLogger(logger: logger, config: testLoggingConfig)) + } + + @Inject + ProgressLoggerFactory getProgressLoggerFactory() { + throw new UnsupportedOperationException() + } + + void jvmArgs(Iterable arguments) { + jvmArgs.addAll(arguments) + } + + void jvmArg(String argument) { + jvmArgs.add(argument) + } + + void systemProperty(String property, Object value) { + systemProperties.put(property, value) + } + + void environment(String key, Object value) { + environmentVariables.put(key, value) + } + + void include(String... includes) { + this.patternSet.include(includes); + } + + void include(Iterable includes) { + this.patternSet.include(includes); + } + + void include(Spec includeSpec) { + this.patternSet.include(includeSpec); + } + + void include(Closure includeSpec) { + this.patternSet.include(includeSpec); + } + + void exclude(String... excludes) { + this.patternSet.exclude(excludes); + } + + void exclude(Iterable excludes) { + this.patternSet.exclude(excludes); + } + + void exclude(Spec excludeSpec) { + this.patternSet.exclude(excludeSpec); + } + + void exclude(Closure excludeSpec) { + this.patternSet.exclude(excludeSpec); + } + + @Input + void testLogging(Closure closure) { + ConfigureUtil.configure(closure, testLoggingConfig) + } + + @Input + void balancers(Closure closure) { + ConfigureUtil.configure(closure, balancersConfig) + } + + @Input + void listeners(Closure closure) { + ConfigureUtil.configure(closure, listenersConfig) + } + + @Option( + option = "tests", + description = "Sets test class or method name to be included. This is for IDEs. Use -Dtests.class and -Dtests.method" + ) + void setTestNameIncludePattern(String testNamePattern) { + // This is only implemented to give support for IDEs running tests. There are 3 patterns expected: + // * An exact test class and method + // * An exact test class + // * A package name prefix, ending with .* + // There is no way to distinguish the first two without looking at classes, so we use the rule + // that class names start with an uppercase letter... + // TODO: this doesn't work yet, but not sure why...intellij says it is using --tests, and this work from the command line... + String[] parts = testNamePattern.split('\\.') + String lastPart = parts[parts.length - 1] + String classname + String methodname = null + if (lastPart.equals('*') || lastPart.charAt(0).isUpperCase()) { + // package name or class name, just pass through + classname = testNamePattern + } else { + // method name, need to separate + methodname = lastPart + classname = testNamePattern.substring(0, testNamePattern.length() - lastPart.length() - 1) + } + ant.setProperty('tests.class', classname) + if (methodname != null) { + ant.setProperty('tests.method', methodname) + } + } + + @TaskAction + void executeTests() { + Map attributes = [ + jvm: jvm, + parallelism: parallelism, + heartbeat: testLoggingConfig.slowTests.heartbeat, + dir: workingDir, + tempdir: new File(workingDir, 'temp'), + haltOnFailure: true, // we want to capture when a build failed, but will decide whether to rethrow later + shuffleOnSlave: shuffleOnSlave, + leaveTemporary: leaveTemporary, + ifNoTests: ifNoTests, + onNonEmptyWorkDirectory: onNonEmptyWorkDirectory, + newenvironment: true + ] + + DefaultLogger listener = null + ByteArrayOutputStream antLoggingBuffer = null + if (logger.isInfoEnabled() == false) { + // in info logging, ant already outputs info level, so we see everything + // but on errors or when debugging, we want to see info level messages + // because junit4 emits jvm output with ant logging + if (testLoggingConfig.outputMode == TestLoggingConfiguration.OutputMode.ALWAYS) { + // we want all output, so just stream directly + listener = new DefaultLogger( + errorPrintStream: System.err, + outputPrintStream: System.out, + messageOutputLevel: Project.MSG_INFO) + } else { + // we want to buffer the info, and emit it if the test fails + antLoggingBuffer = new ByteArrayOutputStream() + PrintStream stream = new PrintStream(antLoggingBuffer, true, "UTF-8") + listener = new DefaultLogger( + errorPrintStream: stream, + outputPrintStream: stream, + messageOutputLevel: Project.MSG_INFO) + } + project.ant.project.addBuildListener(listener) + } + + NamespaceBuilderSupport junit4 = NamespaceBuilder.newInstance(ant, 'junit4') + try { + junit4.junit4(attributes) { + classpath { + pathElement(path: classpath.asPath) + } + if (enableAssertions) { + jvmarg(value: '-ea') + } + if (enableSystemAssertions) { + jvmarg(value: '-esa') + } + for (String arg : jvmArgs) { + jvmarg(value: arg) + } + if (argLine != null) { + jvmarg(line: argLine) + } + testClassesDirs.each { testClassDir -> + fileset(dir: testClassDir) { + patternSet.getIncludes().each { include(name: it) } + patternSet.getExcludes().each { exclude(name: it) } + } + } + for (Map.Entry prop : systemProperties) { + if (prop.getKey().equals('tests.seed')) { + throw new InvalidUserDataException('Seed should be ' + + 'set on the project instead of a system property') + } + if (prop.getValue() instanceof Closure) { + sysproperty key: prop.getKey(), value: (prop.getValue() as Closure).call().toString() + } else { + sysproperty key: prop.getKey(), value: prop.getValue().toString() + } + } + systemProperty 'tests.seed', project.testSeed + for (Map.Entry envvar : environmentVariables) { + env key: envvar.getKey(), value: envvar.getValue().toString() + } + makeListeners() + } + } catch (BuildException e) { + if (antLoggingBuffer != null) { + logger.error('JUnit4 test failed, ant output was:') + logger.error(antLoggingBuffer.toString('UTF-8')) + } + if (haltOnFailure) { + throw e; + } + } + + if (listener != null) { + // remove the listener we added so other ant tasks dont have verbose logging! + project.ant.project.removeBuildListener(listener) + } + } + + static class ListenersElement extends UnknownElement { + AggregatedEventListener[] listeners + + ListenersElement() { + super('listeners') + setNamespace('junit4') + setQName('listeners') + } + + public void handleChildren(Object realThing, RuntimeConfigurable wrapper) { + assert realThing instanceof ListenersList + ListenersList list = (ListenersList)realThing + + for (AggregatedEventListener listener : listeners) { + list.addConfigured(listener) + } + } + } + + /** + * Makes an ant xml element for 'listeners' just as AntBuilder would, except configuring + * the element adds the already created children. + */ + def makeListeners() { + def context = ant.getAntXmlContext() + def parentWrapper = context.currentWrapper() + def parent = parentWrapper.getProxy() + UnknownElement element = new ListenersElement(listeners: listenersConfig.listeners) + element.setProject(context.getProject()) + element.setRealThing(logger) + ((UnknownElement)parent).addChild(element) + RuntimeConfigurable wrapper = new RuntimeConfigurable(element, element.getQName()) + parentWrapper.addChild(wrapper) + return wrapper.getProxy() + } +} diff --git a/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/SlowTestsConfiguration.groovy b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/SlowTestsConfiguration.groovy new file mode 100644 index 0000000000000..2705fdeaacb35 --- /dev/null +++ b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/SlowTestsConfiguration.groovy @@ -0,0 +1,14 @@ +package com.carrotsearch.gradle.junit4 + +class SlowTestsConfiguration { + int heartbeat = 0 + int summarySize = 0 + + void heartbeat(int heartbeat) { + this.heartbeat = heartbeat + } + + void summarySize(int summarySize) { + this.summarySize = summarySize + } +} diff --git a/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/StackTraceFiltersConfiguration.groovy b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/StackTraceFiltersConfiguration.groovy new file mode 100644 index 0000000000000..5e5610ab68e52 --- /dev/null +++ b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/StackTraceFiltersConfiguration.groovy @@ -0,0 +1,14 @@ +package com.carrotsearch.gradle.junit4 + +class StackTraceFiltersConfiguration { + List patterns = new ArrayList<>() + List contains = new ArrayList<>() + + void regex(String pattern) { + patterns.add(pattern) + } + + void contains(String contain) { + contains.add(contain) + } +} diff --git a/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/TestLoggingConfiguration.groovy b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/TestLoggingConfiguration.groovy new file mode 100644 index 0000000000000..97251252f54e2 --- /dev/null +++ b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/TestLoggingConfiguration.groovy @@ -0,0 +1,43 @@ +package com.carrotsearch.gradle.junit4 + +import org.gradle.api.tasks.Input +import org.gradle.util.ConfigureUtil + +class TestLoggingConfiguration { + /** Display mode for output streams. */ + static enum OutputMode { + /** Always display the output emitted from tests. */ + ALWAYS, + /** + * Display the output only if a test/ suite failed. This requires internal buffering + * so the output will be shown only after a test completes. + */ + ONERROR, + /** Don't display the output, even on test failures. */ + NEVER + } + + OutputMode outputMode = OutputMode.ONERROR + SlowTestsConfiguration slowTests = new SlowTestsConfiguration() + StackTraceFiltersConfiguration stackTraceFilters = new StackTraceFiltersConfiguration() + + /** Summarize the first N failures at the end of the test. */ + @Input + int showNumFailuresAtEnd = 3 // match TextReport default + + void slowTests(Closure closure) { + ConfigureUtil.configure(closure, slowTests) + } + + void stackTraceFilters(Closure closure) { + ConfigureUtil.configure(closure, stackTraceFilters) + } + + void outputMode(String mode) { + outputMode = mode.toUpperCase() as OutputMode + } + + void showNumFailuresAtEnd(int n) { + showNumFailuresAtEnd = n + } +} diff --git a/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/TestProgressLogger.groovy b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/TestProgressLogger.groovy new file mode 100644 index 0000000000000..05248fc581e96 --- /dev/null +++ b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/TestProgressLogger.groovy @@ -0,0 +1,193 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.carrotsearch.gradle.junit4 + +import com.carrotsearch.ant.tasks.junit4.JUnit4 +import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.eventbus.Subscribe +import com.carrotsearch.ant.tasks.junit4.events.TestStartedEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedQuitEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedStartEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedSuiteResultEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedSuiteStartedEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedTestResultEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.ChildBootstrap +import com.carrotsearch.ant.tasks.junit4.events.aggregated.HeartBeatEvent +import com.carrotsearch.ant.tasks.junit4.listeners.AggregatedEventListener +import org.gradle.internal.logging.progress.ProgressLogger +import org.gradle.internal.logging.progress.ProgressLoggerFactory +import org.junit.runner.Description + +import static com.carrotsearch.ant.tasks.junit4.FormattingUtils.formatDurationInSeconds +import static com.carrotsearch.ant.tasks.junit4.events.aggregated.TestStatus.ERROR +import static com.carrotsearch.ant.tasks.junit4.events.aggregated.TestStatus.FAILURE +import static com.carrotsearch.ant.tasks.junit4.events.aggregated.TestStatus.IGNORED +import static com.carrotsearch.ant.tasks.junit4.events.aggregated.TestStatus.IGNORED_ASSUMPTION +import static com.carrotsearch.ant.tasks.junit4.events.aggregated.TestStatus.OK + +/** + * Adapts junit4's event listeners into gradle's ProgressLogger. Note that + * junit4 guarantees (via guava) that methods on this class won't be called by + * multiple threads simultaneously which is helpful in making it simpler. + * + * Every time a test finishes this class will update the logger. It will log + * the last finished test method on the logger line until the first suite + * finishes. Once the first suite finishes it always logs the last finished + * suite. This means that in test runs with a single suite the logger will be + * updated with the test name the whole time which is useful because these runs + * usually have longer individual tests. For test runs with lots of suites the + * majority of the time is spent showing the last suite that finished which is + * more useful for those test runs because test methods there tend to be very + * quick. + */ +class TestProgressLogger implements AggregatedEventListener { + /** Factory to build a progress logger when testing starts */ + ProgressLoggerFactory factory + ProgressLogger parentProgressLogger + ProgressLogger suiteLogger + ProgressLogger testLogger + ProgressLogger[] slaveLoggers + int totalSuites + int totalSlaves + + // Counters incremented test completion. + volatile int suitesCompleted = 0 + volatile int testsCompleted = 0 + volatile int testsFailed = 0 + volatile int testsIgnored = 0 + + @Subscribe + void onStart(AggregatedStartEvent e) throws IOException { + totalSuites = e.suiteCount + totalSlaves = e.slaveCount + parentProgressLogger = factory.newOperation(TestProgressLogger) + parentProgressLogger.setDescription('Randomized test runner') + parentProgressLogger.started() + + suiteLogger = factory.newOperation(TestProgressLogger, parentProgressLogger) + suiteLogger.setDescription('Suite logger') + suiteLogger.started("Suites: 0/" + totalSuites) + testLogger = factory.newOperation(TestProgressLogger, parentProgressLogger) + testLogger.setDescription('Test logger') + testLogger.started('Tests: completed: 0, failed: 0, ignored: 0') + slaveLoggers = new ProgressLogger[e.slaveCount] + for (int i = 0; i < e.slaveCount; ++i) { + slaveLoggers[i] = factory.newOperation(TestProgressLogger, parentProgressLogger) + slaveLoggers[i].setDescription("J${i} test logger") + slaveLoggers[i].started("J${i}: initializing...") + } + } + + @Subscribe + void onChildBootstrap(ChildBootstrap e) throws IOException { + slaveLoggers[e.getSlave().id].progress("J${e.slave.id}: starting (pid ${e.slave.pidString})") + } + + @Subscribe + void onQuit(AggregatedQuitEvent e) throws IOException { + // if onStart was never called (eg no matching tests), suiteLogger and all the other loggers will be null + if (suiteLogger != null) { + suiteLogger.completed() + testLogger.completed() + for (ProgressLogger slaveLogger : slaveLoggers) { + slaveLogger.completed() + } + parentProgressLogger.completed() + } + } + + @Subscribe + void onSuiteStart(AggregatedSuiteStartedEvent e) throws IOException { + String suiteName = simpleName(e.suiteStartedEvent.description) + slaveLoggers[e.slave.id].progress("J${e.slave.id}: ${suiteName} - initializing") + } + + @Subscribe + void onSuiteResult(AggregatedSuiteResultEvent e) throws IOException { + suitesCompleted++ + suiteLogger.progress("Suites: " + suitesCompleted + "/" + totalSuites) + } + + @Subscribe + void onTestResult(AggregatedTestResultEvent e) throws IOException { + String statusMessage + testsCompleted++ + switch (e.status) { + case ERROR: + case FAILURE: + testsFailed++ + statusMessage = "failed" + break + case IGNORED: + case IGNORED_ASSUMPTION: + testsIgnored++ + statusMessage = "ignored" + break + case OK: + String time = formatDurationInSeconds(e.executionTime) + statusMessage = "completed [${time}]" + break + default: + throw new IllegalArgumentException("Unknown test status: [${e.status}]") + } + testLogger.progress("Tests: completed: ${testsCompleted}, failed: ${testsFailed}, ignored: ${testsIgnored}") + String testName = testName(e.description) + slaveLoggers[e.slave.id].progress("J${e.slave.id}: ${testName} ${statusMessage}") + } + + @Subscribe + void onTestStarted(TestStartedEvent e) throws IOException { + String testName = testName(e.description) + slaveLoggers[e.slave.id].progress("J${e.slave.id}: ${testName} ...") + } + + @Subscribe + void onHeartbeat(HeartBeatEvent e) throws IOException { + String testName = testName(e.description) + String time = formatDurationInSeconds(e.getNoEventDuration()) + slaveLoggers[e.slave.id].progress("J${e.slave.id}: ${testName} stalled for ${time}") + } + + /** + * Build the test name in the format of . + */ + private static String testName(Description description) { + String className = simpleName(description) + if (description == null) { + return className + "." + "" + } + return className + "." + description.methodName + } + + /** + * Extract a Class#getSimpleName style name from Class#getName style + * string. We can't just use Class#getSimpleName because junit descriptions + * don't always set the class field but they always set the className + * field. + */ + private static String simpleName(Description description) { + if (description == null) { + return "" + } + return description.className.substring(description.className.lastIndexOf('.') + 1) + } + + @Override + void setOuter(JUnit4 junit) {} +} diff --git a/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/TestReportLogger.groovy b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/TestReportLogger.groovy new file mode 100644 index 0000000000000..6ed6ecf86196d --- /dev/null +++ b/buildSrc/src/main/groovy/com/carrotsearch/gradle/junit4/TestReportLogger.groovy @@ -0,0 +1,369 @@ +package com.carrotsearch.gradle.junit4 + +import com.carrotsearch.ant.tasks.junit4.JUnit4 +import com.carrotsearch.ant.tasks.junit4.Pluralize +import com.carrotsearch.ant.tasks.junit4.TestsSummaryEventListener +import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.base.Strings +import com.carrotsearch.ant.tasks.junit4.dependencies.com.google.common.eventbus.Subscribe +import com.carrotsearch.ant.tasks.junit4.events.EventType +import com.carrotsearch.ant.tasks.junit4.events.IEvent +import com.carrotsearch.ant.tasks.junit4.events.IStreamEvent +import com.carrotsearch.ant.tasks.junit4.events.SuiteStartedEvent +import com.carrotsearch.ant.tasks.junit4.events.TestFinishedEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedQuitEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedResultEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedStartEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedSuiteResultEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedSuiteStartedEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.AggregatedTestResultEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.ChildBootstrap +import com.carrotsearch.ant.tasks.junit4.events.aggregated.HeartBeatEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.PartialOutputEvent +import com.carrotsearch.ant.tasks.junit4.events.aggregated.TestStatus +import com.carrotsearch.ant.tasks.junit4.events.mirrors.FailureMirror +import com.carrotsearch.ant.tasks.junit4.listeners.AggregatedEventListener +import com.carrotsearch.ant.tasks.junit4.listeners.StackTraceFilter +import org.apache.tools.ant.filters.TokenFilter +import org.gradle.api.logging.LogLevel +import org.gradle.api.logging.Logger +import org.junit.runner.Description + +import java.util.concurrent.atomic.AtomicInteger + +import static com.carrotsearch.ant.tasks.junit4.FormattingUtils.formatDescription +import static com.carrotsearch.ant.tasks.junit4.FormattingUtils.formatDurationInSeconds +import static com.carrotsearch.ant.tasks.junit4.FormattingUtils.formatTime +import static com.carrotsearch.gradle.junit4.TestLoggingConfiguration.OutputMode + +class TestReportLogger extends TestsSummaryEventListener implements AggregatedEventListener { + + static final String FAILURE_MARKER = " <<< FAILURES!" + + /** Status names column. */ + static EnumMap statusNames; + static { + statusNames = new EnumMap<>(TestStatus.class); + for (TestStatus s : TestStatus.values()) { + statusNames.put(s, + s == TestStatus.IGNORED_ASSUMPTION + ? "IGNOR/A" : s.toString()); + } + } + + JUnit4 owner + + /** Logger to write the report to */ + Logger logger + + TestLoggingConfiguration config + + /** Forked concurrent JVM count. */ + int forkedJvmCount + + /** Format line for JVM ID string. */ + String jvmIdFormat + + /** Output stream that logs messages to the given logger */ + LoggingOutputStream outStream + LoggingOutputStream errStream + + /** A list of failed tests, if to be displayed at the end. */ + List failedTests = new ArrayList<>() + + /** Stack trace filters. */ + StackTraceFilter stackFilter = new StackTraceFilter() + + Map suiteTimes = new HashMap<>() + boolean slowTestsFound = false + + int totalSuites + AtomicInteger suitesCompleted = new AtomicInteger() + + @Subscribe + void onStart(AggregatedStartEvent e) throws IOException { + this.totalSuites = e.getSuiteCount(); + StringBuilder info = new StringBuilder('==> Test Info: ') + info.append('seed=' + owner.getSeed() + '; ') + info.append(Pluralize.pluralize(e.getSlaveCount(), 'jvm') + '=' + e.getSlaveCount() + '; ') + info.append(Pluralize.pluralize(e.getSuiteCount(), 'suite') + '=' + e.getSuiteCount()) + logger.lifecycle(info.toString()) + + forkedJvmCount = e.getSlaveCount(); + jvmIdFormat = " J%-" + (1 + (int) Math.floor(Math.log10(forkedJvmCount))) + "d"; + + outStream = new LoggingOutputStream(logger: logger, level: LogLevel.LIFECYCLE, prefix: " 1> ") + errStream = new LoggingOutputStream(logger: logger, level: LogLevel.ERROR, prefix: " 2> ") + + for (String contains : config.stackTraceFilters.contains) { + TokenFilter.ContainsString containsFilter = new TokenFilter.ContainsString() + containsFilter.setContains(contains) + stackFilter.addContainsString(containsFilter) + } + for (String pattern : config.stackTraceFilters.patterns) { + TokenFilter.ContainsRegex regexFilter = new TokenFilter.ContainsRegex() + regexFilter.setPattern(pattern) + stackFilter.addContainsRegex(regexFilter) + } + } + + @Subscribe + void onChildBootstrap(ChildBootstrap e) throws IOException { + logger.info("Started J" + e.getSlave().id + " PID(" + e.getSlave().getPidString() + ")."); + } + + @Subscribe + void onHeartbeat(HeartBeatEvent e) throws IOException { + logger.warn("HEARTBEAT J" + e.getSlave().id + " PID(" + e.getSlave().getPidString() + "): " + + formatTime(e.getCurrentTime()) + ", stalled for " + + formatDurationInSeconds(e.getNoEventDuration()) + " at: " + + (e.getDescription() == null ? "" : formatDescription(e.getDescription()))) + slowTestsFound = true + } + + @Subscribe + void onQuit(AggregatedQuitEvent e) throws IOException { + if (config.showNumFailuresAtEnd > 0 && !failedTests.isEmpty()) { + List sublist = this.failedTests + StringBuilder b = new StringBuilder() + b.append('Tests with failures') + if (sublist.size() > config.showNumFailuresAtEnd) { + sublist = sublist.subList(0, config.showNumFailuresAtEnd) + b.append(" (first " + config.showNumFailuresAtEnd + " out of " + failedTests.size() + ")") + } + b.append(':\n') + for (Description description : sublist) { + b.append(" - ").append(formatDescription(description, true)).append('\n') + } + logger.warn(b.toString()) + } + if (config.slowTests.summarySize > 0) { + List> sortedSuiteTimes = new ArrayList<>(suiteTimes.entrySet()) + Collections.sort(sortedSuiteTimes, new Comparator>() { + @Override + int compare(Map.Entry o1, Map.Entry o2) { + return o2.value - o1.value // sort descending + } + }) + LogLevel level = slowTestsFound ? LogLevel.WARN : LogLevel.INFO + int numToLog = Math.min(config.slowTests.summarySize, sortedSuiteTimes.size()) + logger.log(level, 'Slow Tests Summary:') + for (int i = 0; i < numToLog; ++i) { + logger.log(level, String.format(Locale.ENGLISH, '%6.2fs | %s', + sortedSuiteTimes.get(i).value / 1000.0, + sortedSuiteTimes.get(i).key)); + } + logger.log(level, '') // extra vertical separation + } + if (failedTests.isEmpty()) { + // summary is already printed for failures + logger.lifecycle('==> Test Summary: ' + getResult().toString()) + } + } + + @Subscribe + void onSuiteStart(AggregatedSuiteStartedEvent e) throws IOException { + if (isPassthrough()) { + SuiteStartedEvent evt = e.getSuiteStartedEvent(); + emitSuiteStart(LogLevel.LIFECYCLE, evt.getDescription()); + } + } + + @Subscribe + void onOutput(PartialOutputEvent e) throws IOException { + if (isPassthrough()) { + // We only allow passthrough output if there is one JVM. + switch (e.getEvent().getType()) { + case EventType.APPEND_STDERR: + ((IStreamEvent) e.getEvent()).copyTo(errStream); + break; + case EventType.APPEND_STDOUT: + ((IStreamEvent) e.getEvent()).copyTo(outStream); + break; + default: + break; + } + } + } + + @Subscribe + void onTestResult(AggregatedTestResultEvent e) throws IOException { + if (isPassthrough() && e.getStatus() != TestStatus.OK) { + flushOutput(); + emitStatusLine(LogLevel.ERROR, e, e.getStatus(), e.getExecutionTime()); + } + + if (!e.isSuccessful()) { + failedTests.add(e.getDescription()); + } + } + + @Subscribe + void onSuiteResult(AggregatedSuiteResultEvent e) throws IOException { + final int completed = suitesCompleted.incrementAndGet(); + + if (e.isSuccessful() && e.getTests().isEmpty()) { + return; + } + if (config.slowTests.summarySize > 0) { + suiteTimes.put(e.getDescription().getDisplayName(), e.getExecutionTime()) + } + + LogLevel level = e.isSuccessful() && config.outputMode != OutputMode.ALWAYS ? LogLevel.INFO : LogLevel.LIFECYCLE + + // We must emit buffered test and stream events (in case of failures). + if (!isPassthrough()) { + emitSuiteStart(level, e.getDescription()) + emitBufferedEvents(level, e) + } + + // Emit a synthetic failure for suite-level errors, if any. + if (!e.getFailures().isEmpty()) { + emitStatusLine(level, e, TestStatus.ERROR, 0) + } + + if (!e.getFailures().isEmpty()) { + failedTests.add(e.getDescription()) + } + + emitSuiteEnd(level, e, completed) + } + + /** Suite prologue. */ + void emitSuiteStart(LogLevel level, Description description) throws IOException { + logger.log(level, 'Suite: ' + description.getDisplayName()); + } + + void emitBufferedEvents(LogLevel level, AggregatedSuiteResultEvent e) throws IOException { + if (config.outputMode == OutputMode.NEVER) { + return + } + + final IdentityHashMap eventMap = new IdentityHashMap<>(); + for (AggregatedTestResultEvent tre : e.getTests()) { + eventMap.put(tre.getTestFinishedEvent(), tre) + } + + final boolean emitOutput = config.outputMode == OutputMode.ALWAYS && isPassthrough() == false || + config.outputMode == OutputMode.ONERROR && e.isSuccessful() == false + + for (IEvent event : e.getEventStream()) { + switch (event.getType()) { + case EventType.APPEND_STDOUT: + if (emitOutput) ((IStreamEvent) event).copyTo(outStream); + break; + + case EventType.APPEND_STDERR: + if (emitOutput) ((IStreamEvent) event).copyTo(errStream); + break; + + case EventType.TEST_FINISHED: + assert eventMap.containsKey(event) + final AggregatedTestResultEvent aggregated = eventMap.get(event); + if (aggregated.getStatus() != TestStatus.OK) { + flushOutput(); + emitStatusLine(level, aggregated, aggregated.getStatus(), aggregated.getExecutionTime()); + } + + default: + break; + } + } + + if (emitOutput) { + flushOutput() + } + } + + void emitSuiteEnd(LogLevel level, AggregatedSuiteResultEvent e, int suitesCompleted) throws IOException { + + final StringBuilder b = new StringBuilder(); + b.append(String.format(Locale.ENGLISH, 'Completed [%d/%d]%s in %.2fs, ', + suitesCompleted, + totalSuites, + e.getSlave().slaves > 1 ? ' on J' + e.getSlave().id : '', + e.getExecutionTime() / 1000.0d)); + b.append(e.getTests().size()).append(Pluralize.pluralize(e.getTests().size(), ' test')); + + int failures = e.getFailureCount(); + if (failures > 0) { + b.append(', ').append(failures).append(Pluralize.pluralize(failures, ' failure')); + } + + int errors = e.getErrorCount(); + if (errors > 0) { + b.append(', ').append(errors).append(Pluralize.pluralize(errors, ' error')); + } + + int ignored = e.getIgnoredCount(); + if (ignored > 0) { + b.append(', ').append(ignored).append(' skipped'); + } + + if (!e.isSuccessful()) { + b.append(' <<< FAILURES!'); + } + + b.append('\n') + logger.log(level, b.toString()); + } + + /** Emit status line for an aggregated event. */ + void emitStatusLine(LogLevel level, AggregatedResultEvent result, TestStatus status, long timeMillis) throws IOException { + final StringBuilder line = new StringBuilder(); + + line.append(Strings.padEnd(statusNames.get(status), 8, ' ' as char)) + line.append(formatDurationInSeconds(timeMillis)) + if (forkedJvmCount > 1) { + line.append(String.format(Locale.ENGLISH, jvmIdFormat, result.getSlave().id)) + } + line.append(' | ') + + line.append(formatDescription(result.getDescription())) + if (!result.isSuccessful()) { + line.append(FAILURE_MARKER) + } + logger.log(level, line.toString()) + + PrintWriter writer = new PrintWriter(new LoggingOutputStream(logger: logger, level: level, prefix: ' > ')) + + if (status == TestStatus.IGNORED && result instanceof AggregatedTestResultEvent) { + writer.write('Cause: ') + writer.write(((AggregatedTestResultEvent) result).getCauseForIgnored()) + writer.flush() + } + + final List failures = result.getFailures(); + if (!failures.isEmpty()) { + int count = 0; + for (FailureMirror fm : failures) { + count++; + if (fm.isAssumptionViolation()) { + writer.write(String.format(Locale.ENGLISH, + 'Assumption #%d: %s', + count, fm.getMessage() == null ? '(no message)' : fm.getMessage())); + } else { + writer.write(String.format(Locale.ENGLISH, + 'Throwable #%d: %s', + count, + stackFilter.apply(fm.getTrace()))); + } + } + writer.flush() + } + } + + void flushOutput() throws IOException { + outStream.flush() + errStream.flush() + } + + /** Returns true if output should be logged immediately. */ + boolean isPassthrough() { + return forkedJvmCount == 1 && config.outputMode == OutputMode.ALWAYS + } + + @Override + void setOuter(JUnit4 task) { + owner = task + } +} diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy index 04e000e2e4366..8a0e7a05327b4 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy @@ -18,13 +18,13 @@ */ package org.elasticsearch.gradle +import com.carrotsearch.gradle.junit4.RandomizedTestingTask import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin import org.apache.commons.io.IOUtils import org.apache.tools.ant.taskdefs.condition.Os import org.eclipse.jgit.lib.Constants import org.eclipse.jgit.lib.RepositoryBuilder import org.elasticsearch.gradle.precommit.PrecommitTasks -import org.elasticsearch.gradle.test.ErrorReportingTestListener import org.gradle.api.GradleException import org.gradle.api.InvalidUserDataException import org.gradle.api.JavaVersion @@ -40,8 +40,8 @@ import org.gradle.api.artifacts.ProjectDependency import org.gradle.api.artifacts.ResolvedArtifact import org.gradle.api.artifacts.dsl.RepositoryHandler import org.gradle.api.credentials.HttpHeaderCredentials -import org.gradle.api.execution.TaskActionListener import org.gradle.api.execution.TaskExecutionGraph +import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.plugins.JavaPlugin import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.plugins.MavenPublishPlugin @@ -51,7 +51,6 @@ import org.gradle.api.tasks.bundling.Jar import org.gradle.api.tasks.compile.GroovyCompile import org.gradle.api.tasks.compile.JavaCompile import org.gradle.api.tasks.javadoc.Javadoc -import org.gradle.api.tasks.testing.Test import org.gradle.authentication.http.HttpHeaderAuthentication import org.gradle.internal.jvm.Jvm import org.gradle.process.ExecResult @@ -84,6 +83,7 @@ class BuildPlugin implements Plugin { ) } project.pluginManager.apply('java') + project.pluginManager.apply('carrotsearch.randomized-testing') configureConfigurations(project) configureJars(project) // jar config must be added before info broker // these plugins add lots of info to our jars @@ -93,12 +93,8 @@ class BuildPlugin implements Plugin { project.pluginManager.apply('nebula.info-scm') project.pluginManager.apply('nebula.info-jar') - // apply global test task failure listener - project.rootProject.pluginManager.apply(TestFailureReportingPlugin) - project.getTasks().create("buildResources", ExportElasticsearchBuildResourcesTask) - setupSeed(project) globalBuildInfo(project) configureRepositories(project) project.ext.versions = VersionProperties.versions @@ -107,7 +103,9 @@ class BuildPlugin implements Plugin { configureJavadoc(project) configureSourcesJar(project) configurePomGeneration(project) - configureTestTasks(project) + + applyCommonTestConfig(project) + configureTest(project) configurePrecommit(project) configureDependenciesInfo(project) } @@ -906,108 +904,128 @@ class BuildPlugin implements Plugin { } } - static void configureTestTasks(Project project) { - // Default test task should run only unit tests - project.tasks.withType(Test).matching { it.name == 'test' }.all { - include '**/*Tests.class' - } - - // none of this stuff is applicable to the `:buildSrc` project tests - if (project.path != ':build-tools') { - File heapdumpDir = new File(project.buildDir, 'heapdump') + static void applyCommonTestConfig(Project project) { + project.tasks.withType(RandomizedTestingTask) {task -> + jvm "${project.runtimeJavaHome}/bin/java" + parallelism System.getProperty('tests.jvms', project.rootProject.ext.defaultParallel) + ifNoTests 'fail' + onNonEmptyWorkDirectory 'wipe' + leaveTemporary true + project.sourceSets.matching { it.name == "test" }.all { test -> + task.testClassesDirs = test.output.classesDirs + task.classpath = test.runtimeClasspath + } + group = JavaBasePlugin.VERIFICATION_GROUP + dependsOn 'testClasses' - project.tasks.withType(Test) { Test test -> - doFirst { - heapdumpDir.mkdirs() - workingDir.mkdirs() + // Make sure all test tasks are configured properly + if (name != "test") { + project.tasks.matching { it.name == "test"}.all { testTask -> + task.shouldRunAfter testTask } + } + if (name == "unitTest") { + include("**/*Tests.class") + } - doLast { - println "Task $test ended" + // TODO: why are we not passing maxmemory to junit4? + jvmArg '-Xmx' + System.getProperty('tests.heap.size', '512m') + jvmArg '-Xms' + System.getProperty('tests.heap.size', '512m') + jvmArg '-XX:+HeapDumpOnOutOfMemoryError' + File heapdumpDir = new File(project.buildDir, 'heapdump') + heapdumpDir.mkdirs() + jvmArg '-XX:HeapDumpPath=' + heapdumpDir + if (project.runtimeJavaVersion >= JavaVersion.VERSION_1_9) { + jvmArg '--illegal-access=warn' + } + argLine System.getProperty('tests.jvm.argline') + + // we use './temp' since this is per JVM and tests are forbidden from writing to CWD + systemProperty 'java.io.tmpdir', './temp' + systemProperty 'java.awt.headless', 'true' + systemProperty 'tests.gradle', 'true' + systemProperty 'tests.artifact', project.name + systemProperty 'tests.task', path + systemProperty 'tests.security.manager', 'true' + systemProperty 'jna.nosys', 'true' + systemProperty 'compiler.java', project.ext.compilerJavaVersion.getMajorVersion() + if (project.ext.inFipsJvm) { + systemProperty 'runtime.java', project.ext.runtimeJavaVersion.getMajorVersion() + "FIPS" + } else { + systemProperty 'runtime.java', project.ext.runtimeJavaVersion.getMajorVersion() + } + // TODO: remove setting logging level via system property + systemProperty 'tests.logger.level', 'WARN' + for (Map.Entry property : System.properties.entrySet()) { + if (property.getKey().startsWith('tests.') || + property.getKey().startsWith('es.')) { + if (property.getKey().equals('tests.seed')) { + /* The seed is already set on the project so we + * shouldn't attempt to override it. */ + continue; + } + systemProperty property.getKey(), property.getValue() } + } - def listener = new ErrorReportingTestListener(test.testLogging) - test.extensions.add(ErrorReportingTestListener, 'errorReportingTestListener', listener) - addTestOutputListener(listener) - addTestListener(listener) - - executable = "${project.runtimeJavaHome}/bin/java" - workingDir = project.file("${project.buildDir}/testrun/${test.name}") - maxParallelForks = project.rootProject.ext.defaultParallel + // TODO: remove this once ctx isn't added to update script params in 7.0 + systemProperty 'es.scripting.update.ctx_in_params', 'false' - exclude '**/*$*.class' + // Set the system keystore/truststore password if we're running tests in a FIPS-140 JVM + if (project.inFipsJvm) { + systemProperty 'javax.net.ssl.trustStorePassword', 'password' + systemProperty 'javax.net.ssl.keyStorePassword', 'password' + } - jvmArgs "-Xmx${System.getProperty('tests.heap.size', '512m')}", - "-Xms${System.getProperty('tests.heap.size', '512m')}", - '-XX:+HeapDumpOnOutOfMemoryError', - "-XX:HeapDumpPath=$heapdumpDir" + boolean assertionsEnabled = Boolean.parseBoolean(System.getProperty('tests.asserts', 'true')) + enableSystemAssertions assertionsEnabled + enableAssertions assertionsEnabled - if (project.runtimeJavaVersion >= JavaVersion.VERSION_1_9) { - jvmArgs '--illegal-access=warn' + testLogging { + showNumFailuresAtEnd 25 + slowTests { + heartbeat 10 + summarySize 5 } - - if (System.getProperty('tests.jvm.argline')) { - jvmArgs System.getProperty('tests.jvm.argline').split(" ") + stackTraceFilters { + // custom filters: we carefully only omit test infra noise here + contains '.SlaveMain.' + regex(/^(\s+at )(org\.junit\.)/) + // also includes anonymous classes inside these two: + regex(/^(\s+at )(com\.carrotsearch\.randomizedtesting\.RandomizedRunner)/) + regex(/^(\s+at )(com\.carrotsearch\.randomizedtesting\.ThreadLeakControl)/) + regex(/^(\s+at )(com\.carrotsearch\.randomizedtesting\.rules\.)/) + regex(/^(\s+at )(org\.apache\.lucene\.util\.TestRule)/) + regex(/^(\s+at )(org\.apache\.lucene\.util\.AbstractBeforeAfterRule)/) } - - if (Boolean.parseBoolean(System.getProperty('tests.asserts', 'true'))) { - jvmArgs '-ea', '-esa' - } - - // we use './temp' since this is per JVM and tests are forbidden from writing to CWD - systemProperties 'gradle.dist.lib': new File(project.class.location.toURI()).parent, - 'gradle.worker.jar': "${project.gradle.getGradleUserHomeDir()}/caches/${project.gradle.gradleVersion}/workerMain/gradle-worker.jar", - 'gradle.user.home': project.gradle.getGradleUserHomeDir(), - 'java.io.tmpdir': './temp', - 'java.awt.headless': 'true', - 'tests.gradle': 'true', - 'tests.artifact': project.name, - 'tests.task': path, - 'tests.security.manager': 'true', - 'tests.seed': project.testSeed, - 'jna.nosys': 'true', - 'compiler.java': project.ext.compilerJavaVersion.getMajorVersion() - - if (project.ext.inFipsJvm) { - systemProperty 'runtime.java', project.ext.runtimeJavaVersion.getMajorVersion() + "FIPS" + if (System.getProperty('tests.class') != null && System.getProperty('tests.output') == null) { + // if you are debugging, you want to see the output! + outputMode 'always' } else { - systemProperty 'runtime.java', project.ext.runtimeJavaVersion.getMajorVersion() + outputMode System.getProperty('tests.output', 'onerror') } - // TODO: remove setting logging level via system property - systemProperty 'tests.logger.level', 'WARN' - System.getProperties().each { key, value -> - if ((key.startsWith('tests.') || key.startsWith('es.'))) { - systemProperty key, value - } - } - - // TODO: remove this once ctx isn't added to update script params in 7.0 - systemProperty 'es.scripting.update.ctx_in_params', 'false' + } - // Set the system keystore/truststore password if we're running tests in a FIPS-140 JVM - if (project.inFipsJvm) { - systemProperty 'javax.net.ssl.trustStorePassword', 'password' - systemProperty 'javax.net.ssl.keyStorePassword', 'password' - } + balancers { + executionTime cacheFilename: ".local-${project.version}-${name}-execution-times.log" + } - testLogging { - showExceptions = true - showCauses = true - exceptionFormat = 'full' - } + listeners { + junitReport() + } - project.plugins.withType(ShadowPlugin).whenPluginAdded { - // Test against a shadow jar if we made one - classpath -= project.tasks.compileJava.outputs.files - classpath += project.tasks.shadowJar.outputs.files + exclude '**/*$*.class' - dependsOn project.tasks.shadowJar - } + project.plugins.withType(ShadowPlugin).whenPluginAdded { + // Test against a shadow jar if we made one + classpath -= project.tasks.compileJava.outputs.files + classpath += project.tasks.shadowJar.outputs.files + dependsOn project.tasks.shadowJar } } } - private static int findDefaultParallel(Project project) { + private static String findDefaultParallel(Project project) { if (project.file("/proc/cpuinfo").exists()) { // Count physical cores on any Linux distro ( don't count hyper-threading ) Map socketToCore = [:] @@ -1028,7 +1046,7 @@ class BuildPlugin implements Plugin { } } }) - return socketToCore.values().sum() + return socketToCore.values().sum().toString(); } else if ('Mac OS X'.equals(System.getProperty('os.name'))) { // Ask macOS to count physical CPUs for us ByteArrayOutputStream stdout = new ByteArrayOutputStream() @@ -1037,9 +1055,16 @@ class BuildPlugin implements Plugin { args '-n', 'hw.physicalcpu' standardOutput = stdout } - return Integer.parseInt(stdout.toString('UTF-8').trim()) + return stdout.toString('UTF-8').trim(); + } + return 'auto'; + } + + /** Configures the test task */ + static Task configureTest(Project project) { + project.tasks.getByName('test') { + include '**/*Tests.class' } - return Runtime.getRuntime().availableProcessors() / 2 } private static configurePrecommit(Project project) { @@ -1069,58 +1094,4 @@ class BuildPlugin implements Plugin { deps.mappings = project.dependencyLicenses.mappings } } - - /** - * Pins the test seed at configuration time so it isn't different on every - * {@link Test} execution. This is useful if random - * decisions in one run of {@linkplain Test} influence the - * outcome of subsequent runs. Pinning the seed up front like this makes - * the reproduction line from one run be useful on another run. - */ - static String setupSeed(Project project) { - if (project.rootProject.ext.has('testSeed')) { - /* Skip this if we've already pinned the testSeed. It is important - * that this checks the rootProject so that we know we've only ever - * initialized one time. */ - return project.rootProject.ext.testSeed - } - - String testSeed = System.getProperty('tests.seed') - if (testSeed == null) { - long seed = new Random(System.currentTimeMillis()).nextLong() - testSeed = Long.toUnsignedString(seed, 16).toUpperCase(Locale.ROOT) - } - - project.rootProject.ext.testSeed = testSeed - return testSeed - } - - private static class TestFailureReportingPlugin implements Plugin { - @Override - void apply(Project project) { - if (project != project.rootProject) { - throw new IllegalStateException("${this.class.getName()} can only be applied to the root project.") - } - - project.gradle.addListener(new TaskActionListener() { - @Override - void beforeActions(Task task) { - - } - - @Override - void afterActions(Task task) { - if (task instanceof Test) { - ErrorReportingTestListener listener = task.extensions.findByType(ErrorReportingTestListener) - if (listener != null && listener.getFailedTests().size() > 0) { - task.logger.lifecycle("\nTests with failures:") - listener.getFailedTests().each { - task.logger.lifecycle(" - ${it.getFullName()}") - } - } - } - } - }) - } - } } diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/RestIntegTestTask.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/RestIntegTestTask.groovy index df26a5a07cb21..4d9cc38323b13 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/RestIntegTestTask.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/RestIntegTestTask.groovy @@ -18,36 +18,30 @@ */ package org.elasticsearch.gradle.test +import com.carrotsearch.gradle.junit4.RandomizedTestingTask import org.elasticsearch.gradle.VersionProperties import org.elasticsearch.gradle.testclusters.ElasticsearchCluster import org.elasticsearch.gradle.testclusters.TestClustersPlugin import org.gradle.api.DefaultTask import org.gradle.api.Task import org.gradle.api.execution.TaskExecutionAdapter -import org.gradle.api.logging.Logger -import org.gradle.api.logging.Logging import org.gradle.api.tasks.Copy import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskState import org.gradle.api.tasks.options.Option -import org.gradle.api.tasks.testing.Test import org.gradle.plugins.ide.idea.IdeaPlugin -import org.gradle.process.CommandLineArgumentProvider import java.nio.charset.StandardCharsets import java.nio.file.Files import java.util.stream.Stream - /** * A wrapper task around setting up a cluster and running rest tests. */ -class RestIntegTestTask extends DefaultTask { - - private static final Logger LOGGER = Logging.getLogger(RestIntegTestTask) +public class RestIntegTestTask extends DefaultTask { protected ClusterConfiguration clusterConfig - protected Test runner + protected RandomizedTestingTask runner protected Task clusterInit @@ -58,8 +52,8 @@ class RestIntegTestTask extends DefaultTask { @Input Boolean includePackaged = false - RestIntegTestTask() { - runner = project.tasks.create("${name}Runner", Test.class) + public RestIntegTestTask() { + runner = project.tasks.create("${name}Runner", RandomizedTestingTask.class) super.dependsOn(runner) clusterInit = project.tasks.create(name: "${name}Cluster#init", dependsOn: project.testClasses) runner.dependsOn(clusterInit) @@ -77,66 +71,35 @@ class RestIntegTestTask extends DefaultTask { runner.useCluster project.testClusters."$name" } - // disable the build cache for rest test tasks - // there are a number of inputs we aren't properly tracking here so we'll just not cache these for now - runner.outputs.doNotCacheIf('Caching is disabled for REST integration tests') { true } - // override/add more for rest tests - runner.maxParallelForks = 1 + runner.parallelism = '1' runner.include('**/*IT.class') runner.systemProperty('tests.rest.load_packaged', 'false') - /* - * We use lazy-evaluated strings in order to configure system properties whose value will not be known until - * execution time (e.g. cluster port numbers). Adding these via the normal DSL doesn't work as these get treated - * as task inputs and therefore Gradle attempts to snapshot them before/after task execution. This fails due - * to the GStrings containing references to non-serializable objects. - * - * We bypass this by instead passing this system properties vi a CommandLineArgumentProvider. This has the added - * side-effect that these properties are NOT treated as inputs, therefore they don't influence things like the - * build cache key or up to date checking. - */ - def nonInputProperties = new CommandLineArgumentProvider() { - private final Map systemProperties = [:] - - void systemProperty(String key, Object value) { - systemProperties.put(key, value) - } - - @Override - Iterable asArguments() { - return systemProperties.collect { key, value -> - "-D${key}=${value.toString()}".toString() - } - } - } - runner.jvmArgumentProviders.add(nonInputProperties) - runner.ext.nonInputProperties = nonInputProperties - if (System.getProperty("tests.rest.cluster") == null) { if (System.getProperty("tests.cluster") != null) { throw new IllegalArgumentException("tests.rest.cluster and tests.cluster must both be null or non-null") } if (usesTestclusters == true) { ElasticsearchCluster cluster = project.testClusters."${name}" - nonInputProperties.systemProperty('tests.rest.cluster', "${-> cluster.allHttpSocketURI.join(",") }") - nonInputProperties.systemProperty('tests.config.dir', "${-> cluster.singleNode().getConfigDir() }") - nonInputProperties.systemProperty('tests.cluster', "${-> cluster.transportPortURI }") + runner.systemProperty('tests.rest.cluster', {cluster.allHttpSocketURI.join(",") }) + runner.systemProperty('tests.config.dir', {cluster.singleNode().getConfigDir()}) + runner.systemProperty('tests.cluster', {cluster.transportPortURI}) } else { // we pass all nodes to the rest cluster to allow the clients to round-robin between them // this is more realistic than just talking to a single node - nonInputProperties.systemProperty('tests.rest.cluster', "${-> nodes.collect { it.httpUri() }.join(",")}") - nonInputProperties.systemProperty('tests.config.dir', "${-> nodes[0].pathConf}") + runner.systemProperty('tests.rest.cluster', "${-> nodes.collect { it.httpUri() }.join(",")}") + runner.systemProperty('tests.config.dir', "${-> nodes[0].pathConf}") // TODO: our "client" qa tests currently use the rest-test plugin. instead they should have their own plugin // that sets up the test cluster and passes this transport uri instead of http uri. Until then, we pass // both as separate sysprops - nonInputProperties.systemProperty('tests.cluster', "${-> nodes[0].transportUri()}") + runner.systemProperty('tests.cluster', "${-> nodes[0].transportUri()}") // dump errors and warnings from cluster log on failure TaskExecutionAdapter logDumpListener = new TaskExecutionAdapter() { @Override void afterExecute(Task task, TaskState state) { - if (task == runner && state.failure != null) { + if (state.failure != null) { for (NodeInfo nodeInfo : nodes) { printLogExcerpt(nodeInfo) } @@ -231,9 +194,9 @@ class RestIntegTestTask extends DefaultTask { /** Print out an excerpt of the log from the given node. */ protected static void printLogExcerpt(NodeInfo nodeInfo) { File logFile = new File(nodeInfo.homeDir, "logs/${nodeInfo.clusterName}.log") - LOGGER.lifecycle("\nCluster ${nodeInfo.clusterName} - node ${nodeInfo.nodeNum} log excerpt:") - LOGGER.lifecycle("(full log at ${logFile})") - LOGGER.lifecycle('-----------------------------------------') + println("\nCluster ${nodeInfo.clusterName} - node ${nodeInfo.nodeNum} log excerpt:") + println("(full log at ${logFile})") + println('-----------------------------------------') Stream stream = Files.lines(logFile.toPath(), StandardCharsets.UTF_8) try { boolean inStartup = true @@ -248,9 +211,9 @@ class RestIntegTestTask extends DefaultTask { } if (inStartup || inExcerpt) { if (linesSkipped != 0) { - LOGGER.lifecycle("... SKIPPED ${linesSkipped} LINES ...") + println("... SKIPPED ${linesSkipped} LINES ...") } - LOGGER.lifecycle(line) + println(line) linesSkipped = 0 } else { ++linesSkipped @@ -262,7 +225,7 @@ class RestIntegTestTask extends DefaultTask { } finally { stream.close() } - LOGGER.lifecycle('=========================================') + println('=========================================') } diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneRestTestPlugin.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneRestTestPlugin.groovy index 2a858206ebd72..9e41466ebdd73 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneRestTestPlugin.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneRestTestPlugin.groovy @@ -20,8 +20,7 @@ package org.elasticsearch.gradle.test - -import groovy.transform.CompileStatic +import com.carrotsearch.gradle.junit4.RandomizedTestingPlugin import org.elasticsearch.gradle.BuildPlugin import org.elasticsearch.gradle.ExportElasticsearchBuildResourcesTask import org.elasticsearch.gradle.VersionProperties @@ -29,66 +28,48 @@ import org.elasticsearch.gradle.precommit.PrecommitTasks import org.gradle.api.InvalidUserDataException import org.gradle.api.Plugin import org.gradle.api.Project -import org.gradle.api.artifacts.Configuration import org.gradle.api.plugins.JavaBasePlugin -import org.gradle.api.plugins.JavaPlugin -import org.gradle.api.tasks.SourceSet -import org.gradle.api.tasks.SourceSetContainer import org.gradle.api.tasks.compile.JavaCompile -import org.gradle.api.tasks.testing.Test -import org.gradle.plugins.ide.eclipse.model.EclipseModel -import org.gradle.plugins.ide.idea.model.IdeaModel - /** * Configures the build to compile tests against Elasticsearch's test framework * and run REST tests. Use BuildPlugin if you want to build main code as well * as tests. */ -@CompileStatic -class StandaloneRestTestPlugin implements Plugin { +public class StandaloneRestTestPlugin implements Plugin { @Override - void apply(Project project) { + public void apply(Project project) { if (project.pluginManager.hasPlugin('elasticsearch.build')) { throw new InvalidUserDataException('elasticsearch.standalone-test ' + 'elasticsearch.standalone-rest-test, and elasticsearch.build ' + 'are mutually exclusive') } project.pluginManager.apply(JavaBasePlugin) + project.pluginManager.apply(RandomizedTestingPlugin) project.getTasks().create("buildResources", ExportElasticsearchBuildResourcesTask) BuildPlugin.globalBuildInfo(project) BuildPlugin.configureRepositories(project) - BuildPlugin.configureTestTasks(project) + BuildPlugin.applyCommonTestConfig(project) // only setup tests to build - SourceSetContainer sourceSets = project.extensions.getByType(SourceSetContainer) - SourceSet testSourceSet = sourceSets.create('test') - - project.tasks.withType(Test) { Test test -> - test.testClassesDirs = testSourceSet.output.classesDirs - test.classpath = testSourceSet.runtimeClasspath - } - + project.sourceSets.create('test') // create a compileOnly configuration as others might expect it project.configurations.create("compileOnly") project.dependencies.add('testCompile', "org.elasticsearch.test:framework:${VersionProperties.elasticsearch}") - EclipseModel eclipse = project.extensions.getByType(EclipseModel) - eclipse.classpath.sourceSets = [testSourceSet] - eclipse.classpath.plusConfigurations = [project.configurations.getByName(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME)] - - IdeaModel idea = project.extensions.getByType(IdeaModel) - idea.module.testSourceDirs += testSourceSet.java.srcDirs - idea.module.scopes.put('TEST', [plus: [project.configurations.getByName(JavaPlugin.TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME)]] as Map>) + project.eclipse.classpath.sourceSets = [project.sourceSets.test] + project.eclipse.classpath.plusConfigurations = [project.configurations.testRuntime] + project.idea.module.testSourceDirs += project.sourceSets.test.java.srcDirs + project.idea.module.scopes['TEST'] = [plus: [project.configurations.testRuntime]] PrecommitTasks.create(project, false) - project.tasks.getByName('check').dependsOn(project.tasks.getByName('precommit')) + project.check.dependsOn(project.precommit) - project.tasks.withType(JavaCompile) { JavaCompile task -> + project.tasks.withType(JavaCompile) { // This will be the default in Gradle 5.0 - if (task.options.compilerArgs.contains("-processor") == false) { - task.options.compilerArgs << '-proc:none' + if (options.compilerArgs.contains("-processor") == false) { + options.compilerArgs << '-proc:none' } } } diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneTestPlugin.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneTestPlugin.groovy index ccdffd6458aa4..95818240cdaaa 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneTestPlugin.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/test/StandaloneTestPlugin.groovy @@ -19,30 +19,34 @@ package org.elasticsearch.gradle.test -import groovy.transform.CompileStatic +import com.carrotsearch.gradle.junit4.RandomizedTestingTask import org.elasticsearch.gradle.BuildPlugin import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.JavaBasePlugin -import org.gradle.api.tasks.testing.Test /** * Configures the build to compile against Elasticsearch's test framework and * run integration and unit tests. Use BuildPlugin if you want to build main * code as well as tests. */ -@CompileStatic -class StandaloneTestPlugin implements Plugin { +public class StandaloneTestPlugin implements Plugin { @Override - void apply(Project project) { + public void apply(Project project) { project.pluginManager.apply(StandaloneRestTestPlugin) - Test test = project.tasks.create('test', Test) - test.group = JavaBasePlugin.VERIFICATION_GROUP - test.description = 'Runs unit tests that are separate' - + Map testOptions = [ + name: 'test', + type: RandomizedTestingTask, + dependsOn: 'testClasses', + group: JavaBasePlugin.VERIFICATION_GROUP, + description: 'Runs unit tests that are separate' + ] + RandomizedTestingTask test = project.tasks.create(testOptions) BuildPlugin.configureCompile(project) - test.mustRunAfter(project.tasks.getByName('precommit')) - project.tasks.getByName('check').dependsOn(test) + test.classpath = project.sourceSets.test.runtimeClasspath + test.testClassesDirs = project.sourceSets.test.output.classesDirs + test.mustRunAfter(project.precommit) + project.check.dependsOn(test) } } diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/vagrant/TapLoggerOutputStream.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/vagrant/TapLoggerOutputStream.groovy index 0be294fb00523..e15759a1fe588 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/vagrant/TapLoggerOutputStream.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/vagrant/TapLoggerOutputStream.groovy @@ -18,7 +18,7 @@ */ package org.elasticsearch.gradle.vagrant -import org.elasticsearch.gradle.LoggingOutputStream +import com.carrotsearch.gradle.junit4.LoggingOutputStream import org.gradle.api.GradleScriptException import org.gradle.api.logging.Logger import org.gradle.internal.logging.progress.ProgressLogger diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/vagrant/VagrantLoggerOutputStream.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/vagrant/VagrantLoggerOutputStream.groovy index f3031f73c236d..e899c0171298b 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/vagrant/VagrantLoggerOutputStream.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/vagrant/VagrantLoggerOutputStream.groovy @@ -18,7 +18,7 @@ */ package org.elasticsearch.gradle.vagrant -import org.elasticsearch.gradle.LoggingOutputStream +import com.carrotsearch.gradle.junit4.LoggingOutputStream import org.gradle.internal.logging.progress.ProgressLogger /** diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsTasks.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsTasks.java index b2228f5c1b132..04e1343f4ac92 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsTasks.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/TestingConventionsTasks.java @@ -31,10 +31,12 @@ import org.gradle.api.tasks.SourceSetContainer; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.testing.Test; +import org.gradle.api.tasks.util.PatternFilterable; import java.io.File; import java.io.IOException; import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.MalformedURLException; @@ -73,6 +75,17 @@ public TestingConventionsTasks() { public Map> classFilesPerEnabledTask(FileTree testClassFiles) { Map> collector = new HashMap<>(); + // RandomizedTestingTask + collector.putAll( + getProject().getTasks().withType(getRandomizedTestingTask()).stream() + .filter(Task::getEnabled) + .collect(Collectors.toMap( + Task::getPath, + task -> testClassFiles.matching(getRandomizedTestingPatternSet(task)).getFiles() + ) + ) + ); + // Gradle Test collector.putAll( getProject().getTasks().withType(Test.class).stream() @@ -266,6 +279,32 @@ private String collectProblems(String... problems) { .collect(Collectors.joining("\n")); } + @SuppressWarnings("unchecked") + private PatternFilterable getRandomizedTestingPatternSet(Task task) { + try { + if ( + getRandomizedTestingTask().isAssignableFrom(task.getClass()) == false + ) { + throw new IllegalStateException("Expected " + task + " to be RandomizedTestingTask or Test but it was " + task.getClass()); + } + Method getPatternSet = task.getClass().getMethod("getPatternSet"); + return (PatternFilterable) getPatternSet.invoke(task); + } catch (NoSuchMethodException e) { + throw new IllegalStateException("Expecte task to have a `patternSet` " + task, e); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new IllegalStateException("Failed to get pattern set from task" + task, e); + } + } + + @SuppressWarnings("unchecked") + private Class getRandomizedTestingTask() { + try { + return (Class) Class.forName("com.carrotsearch.gradle.junit4.RandomizedTestingTask"); + } catch (ClassNotFoundException | ClassCastException e) { + throw new IllegalStateException("Failed to load randomized testing class", e); + } + } + private String checkNoneExists(String message, Stream> stream) { String problem = stream .map(each -> " * " + each.getName()) diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/test/ErrorReportingTestListener.java b/buildSrc/src/main/java/org/elasticsearch/gradle/test/ErrorReportingTestListener.java deleted file mode 100644 index 397adf3ec946c..0000000000000 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/test/ErrorReportingTestListener.java +++ /dev/null @@ -1,180 +0,0 @@ -package org.elasticsearch.gradle.test; - -import org.gradle.api.internal.tasks.testing.logging.FullExceptionFormatter; -import org.gradle.api.internal.tasks.testing.logging.TestExceptionFormatter; -import org.gradle.api.tasks.testing.TestDescriptor; -import org.gradle.api.tasks.testing.TestListener; -import org.gradle.api.tasks.testing.TestOutputEvent; -import org.gradle.api.tasks.testing.TestOutputListener; -import org.gradle.api.tasks.testing.TestResult; -import org.gradle.api.tasks.testing.logging.TestLogging; - -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -public class ErrorReportingTestListener implements TestOutputListener, TestListener { - private static final String REPRODUCE_WITH_PREFIX = "REPRODUCE WITH"; - - private final TestExceptionFormatter formatter; - private Map> eventBuffer = new ConcurrentHashMap<>(); - private Set failedTests = new LinkedHashSet<>(); - - public ErrorReportingTestListener(TestLogging testLogging) { - this.formatter = new FullExceptionFormatter(testLogging); - } - - @Override - public void onOutput(TestDescriptor testDescriptor, TestOutputEvent outputEvent) { - TestDescriptor suite = testDescriptor.getParent(); - - // Check if this is output from the test suite itself (e.g. afterTest or beforeTest) - if (testDescriptor.isComposite()) { - suite = testDescriptor; - } - - List events = eventBuffer.computeIfAbsent(Descriptor.of(suite), d -> new ArrayList<>()); - events.add(outputEvent); - } - - @Override - public void beforeSuite(TestDescriptor suite) { - - } - - @Override - public void afterSuite(final TestDescriptor suite, TestResult result) { - try { - // if the test suite failed, report all captured output - if (result.getResultType().equals(TestResult.ResultType.FAILURE)) { - List events = eventBuffer.get(Descriptor.of(suite)); - - if (events != null) { - // It's not explicit what the threading guarantees are for TestListener method execution so we'll - // be explicitly safe here to avoid interleaving output from multiple test suites - synchronized (this) { - System.err.println("\n\nSuite: " + suite); - - for (TestOutputEvent event : events) { - log(event.getMessage(), event.getDestination()); - } - } - } - } - } finally { - // make sure we don't hold on to test output in memory after the suite has finished - eventBuffer.remove(Descriptor.of(suite)); - } - } - - @Override - public void beforeTest(TestDescriptor testDescriptor) { - - } - - @Override - public void afterTest(TestDescriptor testDescriptor, TestResult result) { - if (result.getResultType() == TestResult.ResultType.FAILURE) { - failedTests.add(Descriptor.of(testDescriptor)); - - if (testDescriptor.getParent() != null) { - // go back and find the reproduction line for this test failure - List events = eventBuffer.get(Descriptor.of(testDescriptor.getParent())); - for (int i = events.size() - 1; i >= 0; i--) { - String message = events.get(i).getMessage(); - if (message.startsWith(REPRODUCE_WITH_PREFIX)) { - System.err.print('\n' + message); - break; - } - } - - // include test failure exception stacktraces in test suite output log - if (result.getExceptions().size() > 0) { - String message = formatter.format(testDescriptor, result.getExceptions()).substring(4); - - events.add(new TestOutputEvent() { - @Override - public Destination getDestination() { - return Destination.StdErr; - } - - @Override - public String getMessage() { - return message; - } - }); - } - } - } - } - - public Set getFailedTests() { - return failedTests; - } - - private static void log(String message, TestOutputEvent.Destination destination) { - PrintStream out; - String prefix; - - if (destination == TestOutputEvent.Destination.StdOut) { - out = System.out; - prefix = " 1> "; - } else { - out = System.err; - prefix = " 2> "; - } - - if (message.equals("\n")) { - out.print(message); - } else { - out.print(prefix); - out.print(message); - } - } - - /** - * Class for identifying test output sources. We use this rather than Gradle's {@link TestDescriptor} as we want - * to avoid any nasty memory leak issues that come from keeping Gradle implementation types in memory. Since we - * use this a the key for our HashMap, it's best to control the implementation as there's no guarantee that Gradle's - * various {@link TestDescriptor} implementations reliably implement equals and hashCode. - */ - public static class Descriptor { - private final String name; - private final String className; - private final String parent; - - private Descriptor(String name, String className, String parent) { - this.name = name; - this.className = className; - this.parent = parent; - } - - public static Descriptor of(TestDescriptor d) { - return new Descriptor(d.getName(), d.getClassName(), d.getParent() == null ? null : d.getParent().toString()); - } - - public String getFullName() { - return className + "." + name; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Descriptor that = (Descriptor) o; - return Objects.equals(name, that.name) && - Objects.equals(className, that.className) && - Objects.equals(parent, that.parent); - } - - @Override - public int hashCode() { - return Objects.hash(name, className, parent); - } - } -} diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/testfixtures/TestFixturesPlugin.java b/buildSrc/src/main/java/org/elasticsearch/gradle/testfixtures/TestFixturesPlugin.java index b930955236fb8..3d64578e0147b 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/testfixtures/TestFixturesPlugin.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/testfixtures/TestFixturesPlugin.java @@ -32,8 +32,9 @@ import org.gradle.api.plugins.BasePlugin; import org.gradle.api.plugins.ExtraPropertiesExtension; import org.gradle.api.tasks.TaskContainer; -import org.gradle.api.tasks.testing.Test; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Collections; import java.util.function.BiConsumer; @@ -102,7 +103,7 @@ public void apply(Project project) { .matching(fixtureProject -> fixtureProject.equals(project) == false) .all(fixtureProject -> project.evaluationDependsOn(fixtureProject.getPath())); - conditionTaskByType(tasks, extension, Test.class); + conditionTaskByType(tasks, extension, getTaskClass("com.carrotsearch.gradle.junit4.RandomizedTestingTask")); conditionTaskByType(tasks, extension, getTaskClass("org.elasticsearch.gradle.test.RestIntegTestTask")); conditionTaskByType(tasks, extension, TestingConventionsTasks.class); conditionTaskByType(tasks, extension, ComposeUp.class); @@ -115,14 +116,18 @@ public void apply(Project project) { return; } - tasks.withType(Test.class, task -> + tasks.withType(getTaskClass("com.carrotsearch.gradle.junit4.RandomizedTestingTask"), task -> extension.fixtures.all(fixtureProject -> { - fixtureProject.getTasks().matching(it -> it.getName().equals("buildFixture")).all(task::dependsOn); - fixtureProject.getTasks().matching(it -> it.getName().equals("composeDown")).all(task::finalizedBy); + fixtureProject.getTasks().matching(it -> it.getName().equals("buildFixture")).all(buildFixture -> + task.dependsOn(buildFixture) + ); + fixtureProject.getTasks().matching(it -> it.getName().equals("composeDown")).all(composeDown -> + task.finalizedBy(composeDown) + ); configureServiceInfoForTask( task, fixtureProject, - task::systemProperty + (name, port) -> setSystemProperty(task, name, port) ); task.dependsOn(fixtureProject.getTasks().getByName("postProcessFixture")); }) @@ -177,6 +182,17 @@ public boolean dockerComposeSupported(Project project) { return hasDockerCompose && Boolean.parseBoolean(System.getProperty("tests.fixture.enabled", "true")); } + private void setSystemProperty(Task task, String name, Object value) { + try { + Method systemProperty = task.getClass().getMethod("systemProperty", String.class, Object.class); + systemProperty.invoke(task, name, value); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException("Could not find systemProperty method on RandomizedTestingTask", e); + } catch (IllegalAccessException | InvocationTargetException e) { + throw new IllegalArgumentException("Could not call systemProperty method on RandomizedTestingTask", e); + } + } + private void disableTaskByType(TaskContainer tasks, Class type) { tasks.withType(type, task -> task.setEnabled(false)); } diff --git a/buildSrc/src/main/resources/META-INF/gradle-plugins/carrotsearch.randomized-testing.properties b/buildSrc/src/main/resources/META-INF/gradle-plugins/carrotsearch.randomized-testing.properties new file mode 100644 index 0000000000000..e1a1b8297c8eb --- /dev/null +++ b/buildSrc/src/main/resources/META-INF/gradle-plugins/carrotsearch.randomized-testing.properties @@ -0,0 +1 @@ +implementation-class=com.carrotsearch.gradle.junit4.RandomizedTestingPlugin diff --git a/buildSrc/src/test/java/org/elasticsearch/gradle/precommit/TestingConventionsTasksIT.java b/buildSrc/src/test/java/org/elasticsearch/gradle/precommit/TestingConventionsTasksIT.java index c6e1e2783cebc..39ab8a6734c58 100644 --- a/buildSrc/src/test/java/org/elasticsearch/gradle/precommit/TestingConventionsTasksIT.java +++ b/buildSrc/src/test/java/org/elasticsearch/gradle/precommit/TestingConventionsTasksIT.java @@ -62,7 +62,7 @@ public void testNoEmptyTasks() { BuildResult result = runner.buildAndFail(); assertOutputContains(result.getOutput(), "Expected at least one test class included in task :empty_test_task:emptyTest, but found none.", - "Expected at least one test class included in task :empty_test_task:test, but found none." + "Expected at least one test class included in task :empty_test_task:emptyTestRandomized, but found none." ); } @@ -71,8 +71,9 @@ public void testAllTestTasksIncluded() { .withArguments("clean", ":all_classes_in_tasks:testingConventions", "-i", "-s"); BuildResult result = runner.buildAndFail(); assertOutputContains(result.getOutput(), - "Test classes are not included in any enabled task (:all_classes_in_tasks:test):", - " * org.elasticsearch.gradle.testkit.NamingConventionIT" + "Test classes are not included in any enabled task (:all_classes_in_tasks:emptyTestRandomized):", + " * org.elasticsearch.gradle.testkit.NamingConventionIT", + " * org.elasticsearch.gradle.testkit.NamingConventionTests" ); } diff --git a/buildSrc/src/testKit/elasticsearch.build/build.gradle b/buildSrc/src/testKit/elasticsearch.build/build.gradle index 8020935f67e80..409367da3146a 100644 --- a/buildSrc/src/testKit/elasticsearch.build/build.gradle +++ b/buildSrc/src/testKit/elasticsearch.build/build.gradle @@ -27,7 +27,7 @@ forbiddenApisTest.enabled = false // requires dependency on testing fw jarHell.enabled = false // we don't have tests for now -test.enabled = false +unitTest.enabled = false task hello { doFirst { diff --git a/buildSrc/src/testKit/testingConventions/build.gradle b/buildSrc/src/testKit/testingConventions/build.gradle index dd82a18085fa1..0052245099112 100644 --- a/buildSrc/src/testKit/testingConventions/build.gradle +++ b/buildSrc/src/testKit/testingConventions/build.gradle @@ -25,16 +25,22 @@ allprojects { baseClasses = [] } } + + unitTest.enabled = false } project(':empty_test_task') { task emptyTest(type: Test) { } + + task emptyTestRandomized(type: com.carrotsearch.gradle.junit4.RandomizedTestingTask) { + + } } project(':all_classes_in_tasks') { - test { + task emptyTestRandomized(type: com.carrotsearch.gradle.junit4.RandomizedTestingTask) { include "**/Convention*" } } @@ -48,14 +54,14 @@ project(':not_implementing_base') { baseClass 'org.elasticsearch.gradle.testkit.Integration' } } - test { + task randomized(type: com.carrotsearch.gradle.junit4.RandomizedTestingTask) { include "**/*IT.class" include "**/*Tests.class" } } project(':valid_setup_no_base') { - test { + task randomized(type: com.carrotsearch.gradle.junit4.RandomizedTestingTask) { include "**/*IT.class" include "**/*Tests.class" } @@ -66,7 +72,7 @@ project(':tests_in_main') { } project (':valid_setup_with_base') { - test { + task randomized(type: com.carrotsearch.gradle.junit4.RandomizedTestingTask) { include "**/*IT.class" include "**/*Tests.class" } diff --git a/client/benchmark/build.gradle b/client/benchmark/build.gradle index a53f102034009..f8beeafd14e09 100644 --- a/client/benchmark/build.gradle +++ b/client/benchmark/build.gradle @@ -29,7 +29,7 @@ archivesBaseName = 'client-benchmarks' mainClassName = 'org.elasticsearch.client.benchmark.BenchmarkMain' // never try to invoke tests on the benchmark project - there aren't any -test.enabled = false +unitTest.enabled = false dependencies { compile 'org.apache.commons:commons-math3:3.2' diff --git a/client/client-benchmark-noop-api-plugin/build.gradle b/client/client-benchmark-noop-api-plugin/build.gradle index b5a5fb5dc5ed1..6df52237e367e 100644 --- a/client/client-benchmark-noop-api-plugin/build.gradle +++ b/client/client-benchmark-noop-api-plugin/build.gradle @@ -36,5 +36,5 @@ dependenciesInfo.enabled = false compileJava.options.compilerArgs << "-Xlint:-cast,-deprecation,-rawtypes,-try,-unchecked" // no unit tests -test.enabled = false +unitTest.enabled = false integTest.enabled = false diff --git a/client/test/build.gradle b/client/test/build.gradle index faf5fb7bddf46..25cf23672dac6 100644 --- a/client/test/build.gradle +++ b/client/test/build.gradle @@ -53,4 +53,4 @@ dependenciesInfo.enabled = false //we aren't releasing this jar thirdPartyAudit.enabled = false -test.enabled = false +unitTest.enabled = false diff --git a/distribution/archives/integ-test-zip/build.gradle b/distribution/archives/integ-test-zip/build.gradle index f44136b2565cc..d79971907b50d 100644 --- a/distribution/archives/integ-test-zip/build.gradle +++ b/distribution/archives/integ-test-zip/build.gradle @@ -26,7 +26,7 @@ integTestRunner { * when running against an external cluster. */ if (System.getProperty("tests.rest.cluster") == null) { - nonInputProperties.systemProperty 'tests.logfile', + systemProperty 'tests.logfile', "${ -> integTest.nodes[0].homeDir}/logs/${ -> integTest.nodes[0].clusterName }_server.json" } else { systemProperty 'tests.logfile', '--external--' diff --git a/distribution/tools/java-version-checker/build.gradle b/distribution/tools/java-version-checker/build.gradle index c8fe9e1121953..03ac32d20b7d6 100644 --- a/distribution/tools/java-version-checker/build.gradle +++ b/distribution/tools/java-version-checker/build.gradle @@ -7,7 +7,7 @@ forbiddenApisMain { replaceSignatureFiles 'jdk-signatures' } -test.enabled = false +unitTest.enabled = false javadoc.enabled = false loggerUsageCheck.enabled = false jarHell.enabled = false diff --git a/distribution/tools/plugin-cli/build.gradle b/distribution/tools/plugin-cli/build.gradle index 61e3546ed8919..b5acb105407d6 100644 --- a/distribution/tools/plugin-cli/build.gradle +++ b/distribution/tools/plugin-cli/build.gradle @@ -35,7 +35,7 @@ dependencyLicenses { mapping from: /bc.*/, to: 'bouncycastle' } -test { +unitTest { // TODO: find a way to add permissions for the tests in this module systemProperty 'tests.security.manager', 'false' } diff --git a/libs/cli/build.gradle b/libs/cli/build.gradle index b1f3b338255c4..0cd1f256c4037 100644 --- a/libs/cli/build.gradle +++ b/libs/cli/build.gradle @@ -26,7 +26,7 @@ dependencies { compile "org.elasticsearch:elasticsearch-core:${version}" } -test.enabled = false +unitTest.enabled = false // Since CLI does not depend on :server, it cannot run the jarHell task jarHell.enabled = false diff --git a/libs/core/src/main/java/org/elasticsearch/bootstrap/JarHell.java b/libs/core/src/main/java/org/elasticsearch/bootstrap/JarHell.java index 277698bd8cc7f..3de0ae5117e6a 100644 --- a/libs/core/src/main/java/org/elasticsearch/bootstrap/JarHell.java +++ b/libs/core/src/main/java/org/elasticsearch/bootstrap/JarHell.java @@ -196,23 +196,18 @@ public static void checkJarHell(Set urls, Consumer output) throws U // case for tests: where we have class files in the classpath final Path root = PathUtils.get(url.toURI()); final String sep = root.getFileSystem().getSeparator(); - - // don't try and walk class or resource directories that don't exist - // gradle will add these to the classpath even if they never get created - if (Files.exists(root)) { - Files.walkFileTree(root, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - String entry = root.relativize(file).toString(); - if (entry.endsWith(".class")) { - // normalize with the os separator, remove '.class' - entry = entry.replace(sep, ".").substring(0, entry.length() - ".class".length()); - checkClass(clazzes, entry, path); - } - return super.visitFile(file, attrs); + Files.walkFileTree(root, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String entry = root.relativize(file).toString(); + if (entry.endsWith(".class")) { + // normalize with the os separator, remove '.class' + entry = entry.replace(sep, ".").substring(0, entry.length() - ".class".length()); + checkClass(clazzes, entry, path); } - }); - } + return super.visitFile(file, attrs); + } + }); } } } diff --git a/libs/plugin-classloader/build.gradle b/libs/plugin-classloader/build.gradle index d6af6600d3463..4b3e00467b71d 100644 --- a/libs/plugin-classloader/build.gradle +++ b/libs/plugin-classloader/build.gradle @@ -17,7 +17,7 @@ * under the License. */ -test.enabled = false +unitTest.enabled = false // test depend on ES core... forbiddenApisMain.enabled = false diff --git a/modules/lang-painless/build.gradle b/modules/lang-painless/build.gradle index a8733fef90d56..9260f871e47f5 100644 --- a/modules/lang-painless/build.gradle +++ b/modules/lang-painless/build.gradle @@ -37,8 +37,8 @@ dependencyLicenses { mapping from: /asm-.*/, to: 'asm' } -test { - jvmArgs '-XX:-OmitStackTraceInFastThrow' +unitTest { + jvmArg '-XX:-OmitStackTraceInFastThrow' } /* Build Javadoc for the Java classes in Painless's public API that are in the diff --git a/modules/lang-painless/spi/build.gradle b/modules/lang-painless/spi/build.gradle index 7e43a242a23a9..92fd70411f74c 100644 --- a/modules/lang-painless/spi/build.gradle +++ b/modules/lang-painless/spi/build.gradle @@ -37,4 +37,4 @@ dependencies { } // no tests...yet? -test.enabled = false +unitTest.enabled = false diff --git a/modules/reindex/build.gradle b/modules/reindex/build.gradle index da184deedaa11..31fbc3ca1f64e 100644 --- a/modules/reindex/build.gradle +++ b/modules/reindex/build.gradle @@ -45,7 +45,7 @@ run { setting 'reindex.remote.whitelist', '127.0.0.1:*' } -test { +unitTest { /* * We have to disable setting the number of available processors as tests in the * same JVM randomize processors and will step on each other if we allow them to @@ -143,8 +143,8 @@ if (Os.isFamily(Os.FAMILY_WINDOWS)) { systemProperty "tests.fromOld", "true" /* Use a closure on the string to delay evaluation until right before we * run the integration tests so that we can be sure that the file is - * ready. */ - nonInputProperties.systemProperty "es${version}.port", "${ -> fixture.addressAndPort }" + * ready. */ + systemProperty "es${version}.port", "${ -> fixture.addressAndPort }" } } } diff --git a/modules/transport-netty4/build.gradle b/modules/transport-netty4/build.gradle index e08bba94d57e6..787a4b6e9ecff 100644 --- a/modules/transport-netty4/build.gradle +++ b/modules/transport-netty4/build.gradle @@ -47,7 +47,7 @@ dependencyLicenses { mapping from: /netty-.*/, to: 'netty' } -test { +unitTest { /* * We have to disable setting the number of available processors as tests in the same JVM randomize processors and will step on each * other if we allow them to set the number of available processors as it's set-once in Netty. diff --git a/plugins/discovery-ec2/build.gradle b/plugins/discovery-ec2/build.gradle index 107d1ecdde363..f154c3d7189a0 100644 --- a/plugins/discovery-ec2/build.gradle +++ b/plugins/discovery-ec2/build.gradle @@ -64,7 +64,7 @@ task writeTestJavaPolicy { } } -test { +unitTest { dependsOn writeTestJavaPolicy // this is needed for insecure plugins, remove if possible! systemProperty 'tests.artifact', project.name diff --git a/plugins/discovery-gce/build.gradle b/plugins/discovery-gce/build.gradle index 697cc3780a1fd..11d4a7e25fe46 100644 --- a/plugins/discovery-gce/build.gradle +++ b/plugins/discovery-gce/build.gradle @@ -29,7 +29,7 @@ check { dependsOn 'qa:gce:check' } -test { +unitTest { // this is needed for insecure plugins, remove if possible! systemProperty 'tests.artifact', project.name } diff --git a/plugins/examples/custom-suggester/build.gradle b/plugins/examples/custom-suggester/build.gradle index 977e467391d8b..7c0d694e1b5ff 100644 --- a/plugins/examples/custom-suggester/build.gradle +++ b/plugins/examples/custom-suggester/build.gradle @@ -32,4 +32,4 @@ integTestCluster { } // this plugin has no unit tests, only rest tests -tasks.test.enabled = false +tasks.unitTest.enabled = false diff --git a/plugins/examples/painless-whitelist/build.gradle b/plugins/examples/painless-whitelist/build.gradle index 95928c472ca0d..d68a9ee397645 100644 --- a/plugins/examples/painless-whitelist/build.gradle +++ b/plugins/examples/painless-whitelist/build.gradle @@ -35,4 +35,4 @@ if (System.getProperty('tests.distribution') == null) { integTestCluster.distribution = 'oss' } -test.enabled = false +unitTest.enabled = false diff --git a/plugins/examples/rest-handler/build.gradle b/plugins/examples/rest-handler/build.gradle index 98dd093ac17a3..025e570bedea4 100644 --- a/plugins/examples/rest-handler/build.gradle +++ b/plugins/examples/rest-handler/build.gradle @@ -27,7 +27,7 @@ esplugin { } // No unit tests in this example -test.enabled = false +unitTest.enabled = false task exampleFixture(type: org.elasticsearch.gradle.test.AntFixture) { dependsOn testClasses @@ -40,7 +40,7 @@ integTestCluster { dependsOn exampleFixture } integTestRunner { - nonInputProperties.systemProperty 'external.address', "${ -> exampleFixture.addressAndPort }" + systemProperty 'external.address', "${ -> exampleFixture.addressAndPort }" } testingConventions.naming { diff --git a/plugins/examples/script-expert-scoring/build.gradle b/plugins/examples/script-expert-scoring/build.gradle index e9da62acdcff4..b054ab47a3198 100644 --- a/plugins/examples/script-expert-scoring/build.gradle +++ b/plugins/examples/script-expert-scoring/build.gradle @@ -26,5 +26,5 @@ esplugin { noticeFile rootProject.file('NOTICE.txt') } -test.enabled = false +unitTest.enabled = false diff --git a/plugins/repository-hdfs/build.gradle b/plugins/repository-hdfs/build.gradle index 24b03621eba9a..d5addc663ca5b 100644 --- a/plugins/repository-hdfs/build.gradle +++ b/plugins/repository-hdfs/build.gradle @@ -24,7 +24,6 @@ import org.elasticsearch.gradle.test.RestIntegTestTask import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths - apply plugin: 'elasticsearch.test.fixtures' esplugin { @@ -151,9 +150,9 @@ project.afterEvaluate { Task restIntegTestTaskRunner = project.tasks.getByName("${integTestTaskName}Runner") restIntegTestTaskRunner.systemProperty "test.krb5.principal.es", "elasticsearch@${realm}" restIntegTestTaskRunner.systemProperty "test.krb5.principal.hdfs", "hdfs/hdfs.build.elastic.co@${realm}" - restIntegTestTaskRunner.jvmArgs "-Djava.security.krb5.conf=${krb5conf}" + restIntegTestTaskRunner.jvmArg "-Djava.security.krb5.conf=${krb5conf}" if (project.runtimeJavaVersion == JavaVersion.VERSION_1_9) { - restIntegTestTaskRunner.jvmArgs '--add-opens=java.security.jgss/sun.security.krb5=ALL-UNNAMED' + restIntegTestTaskRunner.jvmArg '--add-opens=java.security.jgss/sun.security.krb5=ALL-UNNAMED' } restIntegTestTaskRunner.systemProperty ( "test.krb5.keytab.hdfs", @@ -222,7 +221,7 @@ if (fixtureSupported) { integTestRunner.systemProperty 'tests.rest.suite', 'hdfs_repository' // Only include the HA integration tests for the HA test task - integTestHaRunner.setIncludes(['**/Ha*TestSuiteIT.class']) + integTestHaRunner.patternSet.setIncludes(['**/Ha*TestSuiteIT.class']) } else { if (legalPath) { logger.warn("hdfsFixture unsupported, please set HADOOP_HOME and put HADOOP_HOME\\bin in PATH") @@ -253,7 +252,7 @@ integTestSecureRunner.systemProperty 'tests.rest.suite', 'secure_hdfs_repository // Ignore HA integration Tests. They are included below as part of integTestSecureHa test runner. integTestSecureRunner.exclude('**/Ha*TestSuiteIT.class') // Only include the HA integration tests for the HA test task -integTestSecureHaRunner.setIncludes(['**/Ha*TestSuiteIT.class']) +integTestSecureHaRunner.patternSet.setIncludes(['**/Ha*TestSuiteIT.class']) thirdPartyAudit { ignoreMissingClasses() diff --git a/plugins/repository-s3/build.gradle b/plugins/repository-s3/build.gradle index d933bcef4908c..8a2edeb78c507 100644 --- a/plugins/repository-s3/build.gradle +++ b/plugins/repository-s3/build.gradle @@ -2,6 +2,7 @@ import org.elasticsearch.gradle.BuildPlugin import org.elasticsearch.gradle.MavenFilteringHack import org.elasticsearch.gradle.test.AntFixture import org.elasticsearch.gradle.test.RestIntegTestTask +import com.carrotsearch.gradle.junit4.RandomizedTestingTask /* * Licensed to Elasticsearch under one or more contributor @@ -64,14 +65,14 @@ bundlePlugin { } } -task testRepositoryCreds(type: Test) { +task testRepositoryCreds(type: RandomizedTestingTask) { include '**/RepositoryCredentialsTests.class' include '**/S3BlobStoreRepositoryTests.class' systemProperty 'es.allow_insecure_settings', 'true' } check.dependsOn(testRepositoryCreds) -test { +unitTest { // these are tested explicitly in separate test tasks exclude '**/*CredentialsTests.class' exclude '**/S3BlobStoreRepositoryTests.class' diff --git a/qa/die-with-dignity/build.gradle b/qa/die-with-dignity/build.gradle index 140df6e283ab8..3b2e21fd557e7 100644 --- a/qa/die-with-dignity/build.gradle +++ b/qa/die-with-dignity/build.gradle @@ -27,11 +27,11 @@ esplugin { integTestRunner { systemProperty 'tests.security.manager', 'false' systemProperty 'tests.system_call_filter', 'false' - nonInputProperties.systemProperty 'pidfile', "${-> integTest.getNodes().get(0).pidFile}" - nonInputProperties.systemProperty 'log', "${-> integTest.getNodes().get(0).homeDir}/logs/${-> integTest.getNodes().get(0).clusterName}_server.json" + systemProperty 'pidfile', "${-> integTest.getNodes().get(0).pidFile}" + systemProperty 'log', "${-> integTest.getNodes().get(0).homeDir}/logs/${-> integTest.getNodes().get(0).clusterName}_server.json" systemProperty 'runtime.java.home', "${project.runtimeJavaHome}" } -test.enabled = false +unitTest.enabled = false check.dependsOn integTest diff --git a/qa/evil-tests/build.gradle b/qa/evil-tests/build.gradle index 2f9239e5c2f22..62614ca36cda6 100644 --- a/qa/evil-tests/build.gradle +++ b/qa/evil-tests/build.gradle @@ -31,7 +31,7 @@ dependencies { // TODO: give each evil test its own fresh JVM for more isolation. -test { +unitTest { systemProperty 'tests.security.manager', 'false' } diff --git a/qa/full-cluster-restart/build.gradle b/qa/full-cluster-restart/build.gradle index bceee0ec814ac..60c552fc100b9 100644 --- a/qa/full-cluster-restart/build.gradle +++ b/qa/full-cluster-restart/build.gradle @@ -92,7 +92,7 @@ for (Version version : bwcVersions.indexCompatible) { } } -test.enabled = false // no unit tests for rolling upgrades, only the rest integration test +unitTest.enabled = false // no unit tests for rolling upgrades, only the rest integration test // basic integ tests includes testing bwc against the most recent version task bwcTestSnapshots { diff --git a/qa/logging-config/build.gradle b/qa/logging-config/build.gradle index 6af6532d7cfb3..3f6217ae717e9 100644 --- a/qa/logging-config/build.gradle +++ b/qa/logging-config/build.gradle @@ -32,10 +32,10 @@ integTestCluster { } integTestRunner { - nonInputProperties.systemProperty 'tests.logfile', + systemProperty 'tests.logfile', "${ -> integTest.nodes[0].homeDir}/logs/${ -> integTest.nodes[0].clusterName }_server.log" } -test { +unitTest { systemProperty 'tests.security.manager', 'false' } diff --git a/qa/mixed-cluster/build.gradle b/qa/mixed-cluster/build.gradle index 91480c4e3d244..40ffef5e25d40 100644 --- a/qa/mixed-cluster/build.gradle +++ b/qa/mixed-cluster/build.gradle @@ -60,7 +60,7 @@ for (Version version : bwcVersions.wireCompatible) { } } -test.enabled = false // no unit tests for rolling upgrades, only the rest integration test +unitTest.enabled = false // no unit tests for rolling upgrades, only the rest integration test // basic integ tests includes testing bwc against the most recent version task bwcTestSnapshots { diff --git a/qa/multi-cluster-search/build.gradle b/qa/multi-cluster-search/build.gradle index bca12be6754ab..0835945499d34 100644 --- a/qa/multi-cluster-search/build.gradle +++ b/qa/multi-cluster-search/build.gradle @@ -57,6 +57,6 @@ task integTest { dependsOn = [mixedClusterTest] } -test.enabled = false // no unit tests for multi-cluster-search, only integration tests +unitTest.enabled = false // no unit tests for multi-cluster-search, only integration tests check.dependsOn(integTest) diff --git a/qa/rolling-upgrade/build.gradle b/qa/rolling-upgrade/build.gradle index fae318bd93909..89d9fd1eacaf1 100644 --- a/qa/rolling-upgrade/build.gradle +++ b/qa/rolling-upgrade/build.gradle @@ -138,7 +138,7 @@ for (Version version : bwcVersions.wireCompatible) { } } -test.enabled = false // no unit tests for rolling upgrades, only the rest integration test +unitTest.enabled = false // no unit tests for rolling upgrades, only the rest integration test // basic integ tests includes testing bwc against the most recent version task bwcTestSnapshots { diff --git a/qa/unconfigured-node-name/build.gradle b/qa/unconfigured-node-name/build.gradle index 3b0faa10a7e33..5aba0562e03f6 100644 --- a/qa/unconfigured-node-name/build.gradle +++ b/qa/unconfigured-node-name/build.gradle @@ -29,6 +29,6 @@ integTestCluster { } integTestRunner { - nonInputProperties.systemProperty 'tests.logfile', + systemProperty 'tests.logfile', "${ -> integTest.nodes[0].homeDir}/logs/${ -> integTest.nodes[0].clusterName }_server.json" } diff --git a/qa/vagrant/build.gradle b/qa/vagrant/build.gradle index ac0bfe78aadd3..bd5f3e7a2ac1c 100644 --- a/qa/vagrant/build.gradle +++ b/qa/vagrant/build.gradle @@ -71,7 +71,7 @@ forbiddenApisMain { } // we don't have additional tests for the tests themselves -tasks.test.enabled = false +tasks.unitTest.enabled = false // Tests are destructive and meant to run in a VM, they don't adhere to general conventions testingConventions.enabled = false diff --git a/qa/verify-version-constants/build.gradle b/qa/verify-version-constants/build.gradle index 42c2195dd13fa..14a6b4362f1c6 100644 --- a/qa/verify-version-constants/build.gradle +++ b/qa/verify-version-constants/build.gradle @@ -52,7 +52,7 @@ for (Version version : bwcVersions.indexCompatible) { bwcTest.dependsOn(versionBwcTest) } -test.enabled = false +unitTest.enabled = false task bwcTestSnapshots { if (project.bwc_tests_enabled) { diff --git a/qa/wildfly/build.gradle b/qa/wildfly/build.gradle index f9e43bd45fc5b..fce27e6ab8a36 100644 --- a/qa/wildfly/build.gradle +++ b/qa/wildfly/build.gradle @@ -211,7 +211,7 @@ if (!Os.isFamily(Os.FAMILY_WINDOWS)) { check.dependsOn(integTest) -test.enabled = false +unitTest.enabled = false dependencyLicenses.enabled = false dependenciesInfo.enabled = false diff --git a/rest-api-spec/build.gradle b/rest-api-spec/build.gradle index d95ad476682b1..915c3a68f6e0e 100644 --- a/rest-api-spec/build.gradle +++ b/rest-api-spec/build.gradle @@ -2,5 +2,5 @@ apply plugin: 'elasticsearch.build' apply plugin: 'nebula.maven-base-publish' apply plugin: 'nebula.maven-scm' -test.enabled = false +unitTest.enabled = false jarHell.enabled = false diff --git a/server/build.gradle b/server/build.gradle index 50f142cddc1dd..4fc8c451c9b96 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -17,6 +17,8 @@ * under the License. */ +import com.carrotsearch.gradle.junit4.RandomizedTestingTask + apply plugin: 'elasticsearch.build' apply plugin: 'nebula.optional-base' apply plugin: 'nebula.maven-base-publish' @@ -329,15 +331,14 @@ dependencyLicenses { } if (isEclipse == false || project.path == ":server-tests") { - task integTest(type: Test) { - description = 'Multi-node tests' - mustRunAfter test - + task integTest(type: RandomizedTestingTask, + group: JavaBasePlugin.VERIFICATION_GROUP, + description: 'Multi-node tests', + dependsOn: unitTest.dependsOn) { include '**/*IT.class' } - check.dependsOn integTest - + integTest.mustRunAfter test task internalClusterTest { dependsOn integTest } diff --git a/server/src/main/resources/org/elasticsearch/bootstrap/test-framework.policy b/server/src/main/resources/org/elasticsearch/bootstrap/test-framework.policy index d6b15f3df43dc..a4a33426a43ce 100644 --- a/server/src/main/resources/org/elasticsearch/bootstrap/test-framework.policy +++ b/server/src/main/resources/org/elasticsearch/bootstrap/test-framework.policy @@ -56,8 +56,6 @@ grant codeBase "${codebase.randomizedtesting-runner}" { grant codeBase "${codebase.junit}" { // needed for TestClass creation permission java.lang.RuntimePermission "accessDeclaredMembers"; - // needed for test listener notifications - permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; }; grant codeBase "${codebase.mocksocket}" { @@ -88,20 +86,3 @@ grant codeBase "${codebase.httpasyncclient}" { // rest client uses system properties which gets the default proxy permission java.net.NetPermission "getProxySelector"; }; - -grant codeBase "file:${gradle.dist.lib}/-" { - // gradle test worker code needs a slew of permissions, we give full access here since gradle isn't a production - // dependency and there's no point in exercising the security policy against it - permission java.security.AllPermission; -}; - -grant codeBase "file:${gradle.worker.jar}" { - // gradle test worker code needs a slew of permissions, we give full access here since gradle isn't a production - // dependency and there's no point in exercising the security policy against it - permission java.security.AllPermission; -}; - -grant { - // since the gradle test worker jar is on the test classpath, our tests should be able to read it - permission java.io.FilePermission "${gradle.worker.jar}", "read"; -}; \ No newline at end of file diff --git a/test/fixtures/hdfs-fixture/build.gradle b/test/fixtures/hdfs-fixture/build.gradle index 5dab9d99915b5..bd2dbec6649ab 100644 --- a/test/fixtures/hdfs-fixture/build.gradle +++ b/test/fixtures/hdfs-fixture/build.gradle @@ -23,5 +23,5 @@ dependencies { compile "org.apache.hadoop:hadoop-minicluster:2.8.1" } -test.enabled = false +unitTest.enabled = false thirdPartyAudit.enabled = false diff --git a/test/fixtures/krb5kdc-fixture/build.gradle b/test/fixtures/krb5kdc-fixture/build.gradle index 9787c3527af71..1d224942f1862 100644 --- a/test/fixtures/krb5kdc-fixture/build.gradle +++ b/test/fixtures/krb5kdc-fixture/build.gradle @@ -53,4 +53,4 @@ buildFixture.enabled = false project.ext.krb5Conf = { service -> file("$buildDir/shared/${service}/krb5.conf") } project.ext.krb5Keytabs = { service, fileName -> file("$buildDir/shared/${service}/keytabs/${fileName}") } -test.enabled = false +unitTest.enabled = false diff --git a/test/fixtures/old-elasticsearch/build.gradle b/test/fixtures/old-elasticsearch/build.gradle index 5cfc02bbba3c6..82948a0b3b05a 100644 --- a/test/fixtures/old-elasticsearch/build.gradle +++ b/test/fixtures/old-elasticsearch/build.gradle @@ -24,7 +24,7 @@ a "ports" file with the port on which Elasticsearch is running. """ apply plugin: 'elasticsearch.build' -test.enabled = false +unitTest.enabled = false dependencies { // Just for the constants.... diff --git a/test/framework/build.gradle b/test/framework/build.gradle index 094c574e05188..fbc87988837cc 100644 --- a/test/framework/build.gradle +++ b/test/framework/build.gradle @@ -16,6 +16,7 @@ * specific language governing permissions and limitations * under the License. */ +import com.carrotsearch.gradle.junit4.RandomizedTestingTask; dependencies { compile "org.elasticsearch.client:elasticsearch-rest-client:${version}" @@ -63,12 +64,12 @@ thirdPartyAudit.ignoreMissingClasses ( 'org.jmock.core.Constraint' ) -test { +unitTest { systemProperty 'tests.gradle_index_compat_versions', bwcVersions.indexCompatible.join(',') systemProperty 'tests.gradle_wire_compat_versions', bwcVersions.wireCompatible.join(',') systemProperty 'tests.gradle_unreleased_versions', bwcVersions.unreleased.join(',') } -task integTest(type: Test) { +task integTest(type: RandomizedTestingTask) { include "**/*IT.class" } diff --git a/test/framework/src/main/java/org/elasticsearch/bootstrap/BootstrapForTesting.java b/test/framework/src/main/java/org/elasticsearch/bootstrap/BootstrapForTesting.java index e035b779b3f02..28170c827b3e9 100644 --- a/test/framework/src/main/java/org/elasticsearch/bootstrap/BootstrapForTesting.java +++ b/test/framework/src/main/java/org/elasticsearch/bootstrap/BootstrapForTesting.java @@ -37,7 +37,6 @@ import java.io.InputStream; import java.net.SocketPermission; import java.net.URL; -import java.nio.file.Files; import java.nio.file.Path; import java.security.Permission; import java.security.Permissions; @@ -253,12 +252,9 @@ static Set parseClassPathWithSymlinks() throws Exception { Set raw = JarHell.parseClassPath(); Set cooked = new HashSet<>(raw.size()); for (URL url : raw) { - Path path = PathUtils.get(url.toURI()); - if (Files.exists(path)) { - boolean added = cooked.add(path.toRealPath().toUri().toURL()); - if (added == false) { - throw new IllegalStateException("Duplicate in classpath after resolving symlinks: " + url); - } + boolean added = cooked.add(PathUtils.get(url.toURI()).toRealPath().toUri().toURL()); + if (added == false) { + throw new IllegalStateException("Duplicate in classpath after resolving symlinks: " + url); } } return raw; diff --git a/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java b/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java index b1a4c42cbfd8e..58e126b4bed4a 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java +++ b/test/framework/src/main/java/org/elasticsearch/test/junit/listeners/ReproduceInfoPrinter.java @@ -19,6 +19,7 @@ package org.elasticsearch.test.junit.listeners; import com.carrotsearch.randomizedtesting.ReproduceErrorMessageBuilder; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.lucene.util.Constants; @@ -37,7 +38,6 @@ import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_ITERATIONS; import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_PREFIX; -import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_TESTCLASS; import static com.carrotsearch.randomizedtesting.SysGlobals.SYSPROP_TESTMETHOD; import static org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase.REST_TESTS_BLACKLIST; import static org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase.REST_TESTS_SUITE; @@ -77,14 +77,8 @@ public void testFailure(Failure failure) throws Exception { final String gradlew = Constants.WINDOWS ? "gradlew" : "./gradlew"; final StringBuilder b = new StringBuilder("REPRODUCE WITH: " + gradlew + " "); String task = System.getProperty("tests.task"); - - // append Gradle test runner test filter string + // TODO: enforce (intellij still runs the runner?) or use default "test" but that won't work for integ b.append(task); - b.append(" --tests \""); - b.append(failure.getDescription().getClassName()); - b.append("."); - b.append(failure.getDescription().getMethodName()); - b.append("\""); GradleMessageBuilder gradleMessageBuilder = new GradleMessageBuilder(b); gradleMessageBuilder.appendAllOpts(failure.getDescription()); @@ -112,6 +106,11 @@ public GradleMessageBuilder(StringBuilder b) { public ReproduceErrorMessageBuilder appendAllOpts(Description description) { super.appendAllOpts(description); + if (description.getMethodName() != null) { + //prints out the raw method description instead of methodName(description) which filters out the parameters + super.appendOpt(SYSPROP_TESTMETHOD(), "\"" + description.getMethodName() + "\""); + } + return appendESProperties(); } @@ -129,11 +128,6 @@ public ReproduceErrorMessageBuilder appendOpt(String sysPropName, String value) if (sysPropName.equals(SYSPROP_ITERATIONS())) { // we don't want the iters to be in there! return this; } - if (sysPropName.equals(SYSPROP_TESTCLASS())) { - //don't print out the test class, we print it ourselves in appendAllOpts - //without filtering out the parameters (needed for REST tests) - return this; - } if (sysPropName.equals(SYSPROP_TESTMETHOD())) { //don't print out the test method, we print it ourselves in appendAllOpts //without filtering out the parameters (needed for REST tests) @@ -149,7 +143,7 @@ public ReproduceErrorMessageBuilder appendOpt(String sysPropName, String value) return this; } - private ReproduceErrorMessageBuilder appendESProperties() { + public ReproduceErrorMessageBuilder appendESProperties() { appendProperties("tests.es.logger.level"); if (inVerifyPhase()) { // these properties only make sense for integration tests diff --git a/x-pack/plugin/ccr/build.gradle b/x-pack/plugin/ccr/build.gradle index 12ddcd3995b10..e1ddb2f12d78b 100644 --- a/x-pack/plugin/ccr/build.gradle +++ b/x-pack/plugin/ccr/build.gradle @@ -1,3 +1,5 @@ +import com.carrotsearch.gradle.junit4.RandomizedTestingTask + evaluationDependsOn(xpackModule('core')) apply plugin: 'elasticsearch.esplugin' @@ -19,27 +21,28 @@ compileTestJava.options.compilerArgs << "-Xlint:-try" // Integration Test classes that cannot run with the security manager String[] noSecurityManagerITClasses = [ "**/CloseFollowerIndexIT.class" ] -task internalClusterTestNoSecurityManager(type: Test) { - description = 'Java fantasy integration tests with no security manager' - - include noSecurityManagerITClasses - systemProperty 'es.set.netty.runtime.available.processors', 'false' - systemProperty 'tests.security.manager', 'false' -} - // Instead we create a separate task to run the // tests based on ESIntegTestCase -task internalClusterTest(type: Test) { - description = 'Java fantasy integration tests' - dependsOn internalClusterTestNoSecurityManager - mustRunAfter test - +task internalClusterTest(type: RandomizedTestingTask, + group: JavaBasePlugin.VERIFICATION_GROUP, + description: 'Java fantasy integration tests', + dependsOn: unitTest.dependsOn) { include '**/*IT.class' exclude noSecurityManagerITClasses systemProperty 'es.set.netty.runtime.available.processors', 'false' } - check.dependsOn internalClusterTest +internalClusterTest.mustRunAfter test + +task internalClusterTestNoSecurityManager(type: RandomizedTestingTask, + group: JavaBasePlugin.VERIFICATION_GROUP, + description: 'Java fantasy integration tests with no security manager', + dependsOn: unitTest.dependsOn) { + include noSecurityManagerITClasses + systemProperty 'es.set.netty.runtime.available.processors', 'false' + systemProperty 'tests.security.manager', 'false' +} +internalClusterTest.dependsOn internalClusterTestNoSecurityManager // add all sub-projects of the qa sub-project gradle.projectsEvaluated { diff --git a/x-pack/plugin/ccr/qa/build.gradle b/x-pack/plugin/ccr/qa/build.gradle index d3e95d997c3fb..a70f1cbd0a738 100644 --- a/x-pack/plugin/ccr/qa/build.gradle +++ b/x-pack/plugin/ccr/qa/build.gradle @@ -1,7 +1,7 @@ import org.elasticsearch.gradle.test.RestIntegTestTask apply plugin: 'elasticsearch.build' -test.enabled = false +unitTest.enabled = false dependencies { compile project(':test:framework') diff --git a/x-pack/plugin/ccr/qa/downgrade-to-basic-license/build.gradle b/x-pack/plugin/ccr/qa/downgrade-to-basic-license/build.gradle index cbf30b54d5fdb..bba9709087a56 100644 --- a/x-pack/plugin/ccr/qa/downgrade-to-basic-license/build.gradle +++ b/x-pack/plugin/ccr/qa/downgrade-to-basic-license/build.gradle @@ -53,11 +53,11 @@ followClusterTestCluster { followClusterTestRunner { systemProperty 'java.security.policy', "file://${buildDir}/tmp/java.policy" systemProperty 'tests.target_cluster', 'follow' - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'log', "${-> followClusterTest.getNodes().get(0).homeDir}/logs/" + + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'log', "${-> followClusterTest.getNodes().get(0).homeDir}/logs/" + "${-> followClusterTest.getNodes().get(0).clusterName}_server.json" finalizedBy 'leaderClusterTestCluster#stop' } check.dependsOn followClusterTest -test.enabled = false // no unit tests for multi-cluster-search, only the rest integration test +unitTest.enabled = false // no unit tests for multi-cluster-search, only the rest integration test diff --git a/x-pack/plugin/ccr/qa/multi-cluster/build.gradle b/x-pack/plugin/ccr/qa/multi-cluster/build.gradle index 7c9c581c5be19..5680eb41f3877 100644 --- a/x-pack/plugin/ccr/qa/multi-cluster/build.gradle +++ b/x-pack/plugin/ccr/qa/multi-cluster/build.gradle @@ -36,7 +36,7 @@ middleClusterTestCluster { middleClusterTestRunner { systemProperty 'tests.target_cluster', 'middle' - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" } task followClusterTest(type: RestIntegTestTask) {} @@ -54,11 +54,11 @@ followClusterTestCluster { followClusterTestRunner { systemProperty 'tests.target_cluster', 'follow' - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.middle_host', "${-> middleClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.middle_host', "${-> middleClusterTest.nodes.get(0).httpUri()}" finalizedBy 'leaderClusterTestCluster#stop' finalizedBy 'middleClusterTestCluster#stop' } check.dependsOn followClusterTest -test.enabled = false // no unit tests for multi-cluster-search, only the rest integration test +unitTest.enabled = false // no unit tests for multi-cluster-search, only the rest integration test diff --git a/x-pack/plugin/ccr/qa/non-compliant-license/build.gradle b/x-pack/plugin/ccr/qa/non-compliant-license/build.gradle index 6d294c4075595..d3044f760faf7 100644 --- a/x-pack/plugin/ccr/qa/non-compliant-license/build.gradle +++ b/x-pack/plugin/ccr/qa/non-compliant-license/build.gradle @@ -33,9 +33,9 @@ followClusterTestCluster { followClusterTestRunner { systemProperty 'tests.target_cluster', 'follow' - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" finalizedBy 'leaderClusterTestCluster#stop' } check.dependsOn followClusterTest -test.enabled = false +unitTest.enabled = false diff --git a/x-pack/plugin/ccr/qa/rest/build.gradle b/x-pack/plugin/ccr/qa/rest/build.gradle index b06535a17c096..c890064504b51 100644 --- a/x-pack/plugin/ccr/qa/rest/build.gradle +++ b/x-pack/plugin/ccr/qa/rest/build.gradle @@ -37,4 +37,4 @@ restTestCluster { } check.dependsOn restTest -test.enabled = false +unitTest.enabled = false diff --git a/x-pack/plugin/ccr/qa/restart/build.gradle b/x-pack/plugin/ccr/qa/restart/build.gradle index 8501de714fae6..59082d7819533 100644 --- a/x-pack/plugin/ccr/qa/restart/build.gradle +++ b/x-pack/plugin/ccr/qa/restart/build.gradle @@ -35,7 +35,7 @@ followClusterTestCluster { followClusterTestRunner { systemProperty 'tests.target_cluster', 'follow' - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" } task followClusterRestartTest(type: RestIntegTestTask) {} @@ -53,9 +53,9 @@ followClusterRestartTestCluster { followClusterRestartTestRunner { systemProperty 'tests.target_cluster', 'follow-restart' - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" finalizedBy 'leaderClusterTestCluster#stop' } check.dependsOn followClusterRestartTest -test.enabled = false +unitTest.enabled = false diff --git a/x-pack/plugin/ccr/qa/security/build.gradle b/x-pack/plugin/ccr/qa/security/build.gradle index 0e082f51d71a1..e1a735e0b2668 100644 --- a/x-pack/plugin/ccr/qa/security/build.gradle +++ b/x-pack/plugin/ccr/qa/security/build.gradle @@ -68,9 +68,9 @@ followClusterTestCluster { followClusterTestRunner { systemProperty 'tests.target_cluster', 'follow' - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" finalizedBy 'leaderClusterTestCluster#stop' } check.dependsOn followClusterTest -test.enabled = false // no unit tests for multi-cluster-search, only the rest integration test +unitTest.enabled = false // no unit tests for multi-cluster-search, only the rest integration test diff --git a/x-pack/plugin/core/build.gradle b/x-pack/plugin/core/build.gradle index 7a6673643879a..ed61fc9e3e703 100644 --- a/x-pack/plugin/core/build.gradle +++ b/x-pack/plugin/core/build.gradle @@ -2,6 +2,7 @@ import org.elasticsearch.gradle.MavenFilteringHack import java.nio.file.Files import java.nio.file.Paths +import com.carrotsearch.gradle.junit4.RandomizedTestingTask; apply plugin: 'elasticsearch.esplugin' apply plugin: 'nebula.maven-base-publish' @@ -98,7 +99,7 @@ sourceSets.test.java { srcDir '../../license-tools/src/main/java' } -test { +unitTest { /* * We have to disable setting the number of available processors as tests in the same JVM randomize processors and will step on each * other if we allow them to set the number of available processors as it's set-once in Netty. @@ -138,6 +139,6 @@ thirdPartyAudit.ignoreMissingClasses ( integTest.enabled = false // There are some integ tests that don't require a cluster, we still want to run those -task internalClusterTest(type: Test) { +task internalClusterTest(type: RandomizedTestingTask) { include "**/*IT.class" } diff --git a/x-pack/plugin/ilm/qa/build.gradle b/x-pack/plugin/ilm/qa/build.gradle index 74412a094b489..f2f60527ec4c1 100644 --- a/x-pack/plugin/ilm/qa/build.gradle +++ b/x-pack/plugin/ilm/qa/build.gradle @@ -1,7 +1,7 @@ import org.elasticsearch.gradle.test.RestIntegTestTask apply plugin: 'elasticsearch.build' -test.enabled = false +unitTest.enabled = false dependencies { compile project(':test:framework') diff --git a/x-pack/plugin/ilm/qa/multi-cluster/build.gradle b/x-pack/plugin/ilm/qa/multi-cluster/build.gradle index 76dbf676d738f..d4c24d0195ef6 100644 --- a/x-pack/plugin/ilm/qa/multi-cluster/build.gradle +++ b/x-pack/plugin/ilm/qa/multi-cluster/build.gradle @@ -50,12 +50,12 @@ followClusterTestCluster { followClusterTestRunner { systemProperty 'tests.target_cluster', 'follow' - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(0).transportUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(0).transportUri()}" /* To support taking index snapshots, we have to set path.repo setting */ systemProperty 'tests.path.repo', new File(buildDir, "cluster/shared/repo") finalizedBy 'leaderClusterTestCluster#stop' } check.dependsOn followClusterTest -test.enabled = false // no unit tests for this module, only the rest integration test +unitTest.enabled = false // no unit tests for this module, only the rest integration test diff --git a/x-pack/plugin/ilm/qa/rest/build.gradle b/x-pack/plugin/ilm/qa/rest/build.gradle index c69a3dfce2143..7a79d1c20d936 100644 --- a/x-pack/plugin/ilm/qa/rest/build.gradle +++ b/x-pack/plugin/ilm/qa/rest/build.gradle @@ -42,4 +42,4 @@ restTestCluster { } check.dependsOn restTest -test.enabled = false +unitTest.enabled = false diff --git a/x-pack/plugin/ml/build.gradle b/x-pack/plugin/ml/build.gradle index 6ca1a44c145da..0fe0af236f9ad 100644 --- a/x-pack/plugin/ml/build.gradle +++ b/x-pack/plugin/ml/build.gradle @@ -1,3 +1,5 @@ +import com.carrotsearch.gradle.junit4.RandomizedTestingTask + evaluationDependsOn(xpackModule('core')) apply plugin: 'elasticsearch.esplugin' @@ -92,11 +94,12 @@ integTest.enabled = false // Instead we create a separate task to run the // tests based on ESIntegTestCase -task internalClusterTest(type: Test) { - description = 'Multi-node tests' - - include '**/*IT.class' - systemProperty 'es.set.netty.runtime.available.processors', 'false' +task internalClusterTest(type: RandomizedTestingTask, + group: JavaBasePlugin.VERIFICATION_GROUP, + description: 'Multi-node tests', + dependsOn: unitTest.dependsOn) { + include '**/*IT.class' + systemProperty 'es.set.netty.runtime.available.processors', 'false' } check.dependsOn internalClusterTest internalClusterTest.mustRunAfter test diff --git a/x-pack/plugin/monitoring/build.gradle b/x-pack/plugin/monitoring/build.gradle index 8b6f07787fbc1..9341a957797ba 100644 --- a/x-pack/plugin/monitoring/build.gradle +++ b/x-pack/plugin/monitoring/build.gradle @@ -1,3 +1,5 @@ +import com.carrotsearch.gradle.junit4.RandomizedTestingTask + evaluationDependsOn(xpackModule('core')) apply plugin: 'elasticsearch.esplugin' @@ -56,15 +58,15 @@ integTest.enabled = false // Instead we create a separate task to run the // tests based on ESIntegTestCase -task internalClusterTest(type: Test) { - description = 'Multi-node tests' - mustRunAfter test - - include '**/*IT.class' - systemProperty 'es.set.netty.runtime.available.processors', 'false' +task internalClusterTest(type: RandomizedTestingTask, + group: JavaBasePlugin.VERIFICATION_GROUP, + description: 'Multi-node tests', + dependsOn: unitTest.dependsOn) { + include '**/*IT.class' + systemProperty 'es.set.netty.runtime.available.processors', 'false' } - check.dependsOn internalClusterTest +internalClusterTest.mustRunAfter test // also add an "alias" task to make typing on the command line easier task icTest { task icTest { diff --git a/x-pack/plugin/security/build.gradle b/x-pack/plugin/security/build.gradle index 8ea14c5f6dd2e..63b531b1f3319 100644 --- a/x-pack/plugin/security/build.gradle +++ b/x-pack/plugin/security/build.gradle @@ -304,7 +304,7 @@ run { plugin xpackModule('core') } -test { +unitTest { /* * We have to disable setting the number of available processors as tests in the same JVM randomize processors and will step on each * other if we allow them to set the number of available processors as it's set-once in Netty. diff --git a/x-pack/plugin/security/cli/build.gradle b/x-pack/plugin/security/cli/build.gradle index 19a8d11dd6f0c..1a829704d40bc 100644 --- a/x-pack/plugin/security/cli/build.gradle +++ b/x-pack/plugin/security/cli/build.gradle @@ -23,7 +23,7 @@ dependencyLicenses { } if (project.inFipsJvm) { - test.enabled = false + unitTest.enabled = false testingConventions.enabled = false // Forbiden APIs non-portable checks fail because bouncy castle classes being used from the FIPS JDK since those are // not part of the Java specification - all of this is as designed, so we have to relax this check for FIPS. diff --git a/x-pack/plugin/sql/build.gradle b/x-pack/plugin/sql/build.gradle index c4719aef04ab8..31cec8bbee39f 100644 --- a/x-pack/plugin/sql/build.gradle +++ b/x-pack/plugin/sql/build.gradle @@ -1,3 +1,5 @@ +import com.carrotsearch.gradle.junit4.RandomizedTestingTask + evaluationDependsOn(xpackModule('core')) apply plugin: 'elasticsearch.esplugin' @@ -28,13 +30,14 @@ archivesBaseName = 'x-pack-sql' // All integration tests live in qa modules integTest.enabled = false -task internalClusterTest(type: Test) { - mustRunAfter test +task internalClusterTest(type: RandomizedTestingTask, + group: JavaBasePlugin.VERIFICATION_GROUP, + dependsOn: unitTest.dependsOn) { include '**/*IT.class' systemProperty 'es.set.netty.runtime.available.processors', 'false' } - check.dependsOn internalClusterTest +internalClusterTest.mustRunAfter test dependencies { // "org.elasticsearch.plugin:x-pack-core:${version}" doesn't work with idea because the testArtifacts are also here diff --git a/x-pack/plugin/sql/jdbc/build.gradle b/x-pack/plugin/sql/jdbc/build.gradle index 3c7eb6b804b5a..bec79dabb1465 100644 --- a/x-pack/plugin/sql/jdbc/build.gradle +++ b/x-pack/plugin/sql/jdbc/build.gradle @@ -37,7 +37,7 @@ dependencyLicenses { ignoreSha 'elasticsearch' } -test { +unitTest { // don't use the shaded jar for tests classpath += project.tasks.compileJava.outputs.files classpath -= project.tasks.shadowJar.outputs.files diff --git a/x-pack/plugin/sql/qa/build.gradle b/x-pack/plugin/sql/qa/build.gradle index 4c9fa6de03095..cf0a0dba8ee62 100644 --- a/x-pack/plugin/sql/qa/build.gradle +++ b/x-pack/plugin/sql/qa/build.gradle @@ -30,7 +30,7 @@ dependencies { /* disable unit tests because these are all integration tests used * other qa projects. */ -test.enabled = false +unitTest.enabled = false dependencyLicenses.enabled = false dependenciesInfo.enabled = false diff --git a/x-pack/plugin/sql/qa/security/build.gradle b/x-pack/plugin/sql/qa/security/build.gradle index 50ba4dbf4382c..45ab8c92f1e7f 100644 --- a/x-pack/plugin/sql/qa/security/build.gradle +++ b/x-pack/plugin/sql/qa/security/build.gradle @@ -42,9 +42,9 @@ subprojects { integTestRunner { def today = new Date().format('yyyy-MM-dd') - nonInputProperties.systemProperty 'tests.audit.logfile', + systemProperty 'tests.audit.logfile', "${ -> integTest.nodes[0].homeDir}/logs/${ -> integTest.nodes[0].clusterName }_audit.json" - nonInputProperties.systemProperty 'tests.audit.yesterday.logfile', + systemProperty 'tests.audit.yesterday.logfile', "${ -> integTest.nodes[0].homeDir}/logs/${ -> integTest.nodes[0].clusterName }_audit-${today}.json" } diff --git a/x-pack/plugin/sql/sql-cli/build.gradle b/x-pack/plugin/sql/sql-cli/build.gradle index 6f57ea279c5ab..e519062e14f57 100644 --- a/x-pack/plugin/sql/sql-cli/build.gradle +++ b/x-pack/plugin/sql/sql-cli/build.gradle @@ -106,7 +106,7 @@ task runcli { } // Use the jar for testing so we can get the proper version information -test { +unitTest { classpath -= compileJava.outputs.files classpath -= configurations.compile classpath -= configurations.runtime diff --git a/x-pack/plugin/watcher/build.gradle b/x-pack/plugin/watcher/build.gradle index 8d7c2e06303df..a32a88aaf06e5 100644 --- a/x-pack/plugin/watcher/build.gradle +++ b/x-pack/plugin/watcher/build.gradle @@ -115,7 +115,7 @@ run { plugin xpackModule('core') } -test { +unitTest { /* * We have to disable setting the number of available processors as tests in the same JVM randomize processors and will step on each * other if we allow them to set the number of available processors as it's set-once in Netty. diff --git a/x-pack/qa/evil-tests/build.gradle b/x-pack/qa/evil-tests/build.gradle index d411909fb310b..ad32645b3647c 100644 --- a/x-pack/qa/evil-tests/build.gradle +++ b/x-pack/qa/evil-tests/build.gradle @@ -5,7 +5,7 @@ dependencies { testCompile project(path: xpackModule('security'), configuration: 'testArtifacts') } -test { +unitTest { systemProperty 'tests.security.manager', 'false' include '**/*Tests.class' } diff --git a/x-pack/qa/full-cluster-restart/build.gradle b/x-pack/qa/full-cluster-restart/build.gradle index f3f290c63e121..40dca76abc913 100644 --- a/x-pack/qa/full-cluster-restart/build.gradle +++ b/x-pack/qa/full-cluster-restart/build.gradle @@ -7,7 +7,7 @@ import java.nio.charset.StandardCharsets // Apply the java plugin to this project so the sources can be edited in an IDE apply plugin: 'elasticsearch.standalone-test' -test.enabled = false +unitTest.enabled = false dependencies { // "org.elasticsearch.plugin:x-pack-core:${version}" doesn't work with idea because the testArtifacts are also here @@ -70,19 +70,15 @@ Closure waitWithAuth = { NodeInfo node, AntBuilder ant -> return tmpFile.exists() } +String coreFullClusterRestartPath = project(':qa:full-cluster-restart').projectDir.toPath().resolve('src/test/java').toString() sourceSets { - testLib { + test { java { - srcDir(project(':qa:full-cluster-restart').projectDir.toPath().resolve('src/test/java').toString()) + srcDirs += [coreFullClusterRestartPath] } } - test { - compileClasspath += testLib.output - } } -configurations.testLibCompile.extendsFrom configurations.testCompile - licenseHeaders { approvedLicenses << 'Apache' } diff --git a/x-pack/qa/multi-cluster-search-security/build.gradle b/x-pack/qa/multi-cluster-search-security/build.gradle index c31b2c0ad1d5e..63265b6949f1e 100644 --- a/x-pack/qa/multi-cluster-search-security/build.gradle +++ b/x-pack/qa/multi-cluster-search-security/build.gradle @@ -75,5 +75,5 @@ task integTest { dependsOn = [mixedClusterTest] } -test.enabled = false // no unit tests for multi-cluster-search, only the rest integration test +unitTest.enabled = false // no unit tests for multi-cluster-search, only the rest integration test check.dependsOn(integTest) diff --git a/x-pack/qa/rolling-upgrade-basic/build.gradle b/x-pack/qa/rolling-upgrade-basic/build.gradle index 169ff9c8b154e..5b7cad500361c 100644 --- a/x-pack/qa/rolling-upgrade-basic/build.gradle +++ b/x-pack/qa/rolling-upgrade-basic/build.gradle @@ -120,7 +120,7 @@ for (Version version : bwcVersions.wireCompatible) { } } -test.enabled = false // no unit tests for rolling upgrades, only the rest integration test +unitTest.enabled = false // no unit tests for rolling upgrades, only the rest integration test // basic integ tests includes testing bwc against the most recent version task bwcTestSnapshots { diff --git a/x-pack/qa/rolling-upgrade-multi-cluster/build.gradle b/x-pack/qa/rolling-upgrade-multi-cluster/build.gradle index 19e1f5a716c08..144b410391867 100644 --- a/x-pack/qa/rolling-upgrade-multi-cluster/build.gradle +++ b/x-pack/qa/rolling-upgrade-multi-cluster/build.gradle @@ -45,8 +45,8 @@ for (Version version : bwcVersions.wireCompatible) { systemProperty 'tests.rest.upgrade_state', 'none' systemProperty 'tests.rest.cluster_name', 'leader' - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(0).transportUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(0).transportUri()}" } // ============================================================================================ @@ -76,11 +76,11 @@ for (Version version : bwcVersions.wireCompatible) { systemProperty 'tests.rest.upgrade_state', 'none' systemProperty 'tests.rest.cluster_name', 'follower' - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(0).transportUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(0).transportUri()}" - nonInputProperties.systemProperty 'tests.follower_host', "${-> followerClusterTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.follower_remote_cluster_seed', "${-> followerClusterTest.nodes.get(0).transportUri()}" + systemProperty 'tests.follower_host', "${-> followerClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.follower_remote_cluster_seed', "${-> followerClusterTest.nodes.get(0).transportUri()}" } // ============================================================================================ @@ -119,11 +119,11 @@ for (Version version : bwcVersions.wireCompatible) { systemProperty 'tests.rest.upgrade_state', 'one_third' systemProperty 'tests.rest.cluster_name', 'follower' - nonInputProperties.systemProperty 'tests.follower_host', "${-> followerClusterTest.nodes.get(1).httpUri()}" - nonInputProperties.systemProperty 'tests.follower_remote_cluster_seed', "${-> followerClusterTest.nodes.get(1).transportUri()}" + systemProperty 'tests.follower_host', "${-> followerClusterTest.nodes.get(1).httpUri()}" + systemProperty 'tests.follower_remote_cluster_seed', "${-> followerClusterTest.nodes.get(1).transportUri()}" - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(0).transportUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(0).transportUri()}" finalizedBy "${taskPrefix}#follower#clusterTestCluster#node1.stop" } @@ -140,11 +140,11 @@ for (Version version : bwcVersions.wireCompatible) { systemProperty 'tests.rest.upgrade_state', 'two_third' systemProperty 'tests.rest.cluster_name', 'follower' - nonInputProperties.systemProperty 'tests.follower_host', "${-> followerClusterTest.nodes.get(2).httpUri()}" - nonInputProperties.systemProperty 'tests.follower_remote_cluster_seed', "${-> followerClusterTest.nodes.get(2).transportUri()}" + systemProperty 'tests.follower_host', "${-> followerClusterTest.nodes.get(2).httpUri()}" + systemProperty 'tests.follower_remote_cluster_seed', "${-> followerClusterTest.nodes.get(2).transportUri()}" - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(0).transportUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(0).transportUri()}" finalizedBy "${taskPrefix}#follower#clusterTestCluster#node2.stop" } @@ -161,11 +161,11 @@ for (Version version : bwcVersions.wireCompatible) { systemProperty 'tests.rest.upgrade_state', 'all' systemProperty 'tests.rest.cluster_name', 'follower' - nonInputProperties.systemProperty 'tests.follower_host', "${-> followerOneThirdUpgradedTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.follower_remote_cluster_seed', "${-> followerOneThirdUpgradedTest.nodes.get(0).transportUri()}" + systemProperty 'tests.follower_host', "${-> followerOneThirdUpgradedTest.nodes.get(0).httpUri()}" + systemProperty 'tests.follower_remote_cluster_seed', "${-> followerOneThirdUpgradedTest.nodes.get(0).transportUri()}" - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(0).transportUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(0).transportUri()}" // This is needed, otherwise leader node 0 will stop after the leaderClusterTestRunner task has run. // Here it is ok to stop, because in the next task, the leader node 0 gets upgraded. @@ -188,11 +188,11 @@ for (Version version : bwcVersions.wireCompatible) { systemProperty 'tests.rest.upgrade_state', 'one_third' systemProperty 'tests.rest.cluster_name', 'leader' - nonInputProperties.systemProperty 'tests.follower_host', "${-> followerUpgradedClusterTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.follower_remote_cluster_seed', "${-> followerUpgradedClusterTest.nodes.get(0).transportUri()}" + systemProperty 'tests.follower_host', "${-> followerUpgradedClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.follower_remote_cluster_seed', "${-> followerUpgradedClusterTest.nodes.get(0).transportUri()}" - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(2).httpUri()}" - nonInputProperties.systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(2).transportUri()}" + systemProperty 'tests.leader_host', "${-> leaderClusterTest.nodes.get(2).httpUri()}" + systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderClusterTest.nodes.get(2).transportUri()}" finalizedBy "${taskPrefix}#leader#clusterTestCluster#node1.stop" } @@ -209,11 +209,11 @@ for (Version version : bwcVersions.wireCompatible) { systemProperty 'tests.rest.upgrade_state', 'two_third' systemProperty 'tests.rest.cluster_name', 'leader' - nonInputProperties.systemProperty 'tests.follower_host', "${-> followerUpgradedClusterTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.follower_remote_cluster_seed', "${-> followerUpgradedClusterTest.nodes.get(0).transportUri()}" + systemProperty 'tests.follower_host', "${-> followerUpgradedClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.follower_remote_cluster_seed', "${-> followerUpgradedClusterTest.nodes.get(0).transportUri()}" - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderOneThirdUpgradedTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderOneThirdUpgradedTest.nodes.get(0).transportUri()}" + systemProperty 'tests.leader_host', "${-> leaderOneThirdUpgradedTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderOneThirdUpgradedTest.nodes.get(0).transportUri()}" finalizedBy "${taskPrefix}#leader#clusterTestCluster#node2.stop" } @@ -230,11 +230,11 @@ for (Version version : bwcVersions.wireCompatible) { systemProperty 'tests.rest.upgrade_state', 'all' systemProperty 'tests.rest.cluster_name', 'leader' - nonInputProperties.systemProperty 'tests.follower_host', "${-> followerUpgradedClusterTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.follower_remote_cluster_seed', "${-> followerUpgradedClusterTest.nodes.get(0).transportUri()}" + systemProperty 'tests.follower_host', "${-> followerUpgradedClusterTest.nodes.get(0).httpUri()}" + systemProperty 'tests.follower_remote_cluster_seed', "${-> followerUpgradedClusterTest.nodes.get(0).transportUri()}" - nonInputProperties.systemProperty 'tests.leader_host', "${-> leaderTwoThirdsUpgradedTest.nodes.get(0).httpUri()}" - nonInputProperties.systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderTwoThirdsUpgradedTest.nodes.get(0).transportUri()}" + systemProperty 'tests.leader_host', "${-> leaderTwoThirdsUpgradedTest.nodes.get(0).httpUri()}" + systemProperty 'tests.leader_remote_cluster_seed', "${-> leaderTwoThirdsUpgradedTest.nodes.get(0).transportUri()}" /* * Force stopping all the upgraded nodes after the test runner @@ -255,7 +255,7 @@ for (Version version : bwcVersions.wireCompatible) { } } -test.enabled = false // no unit tests for rolling upgrades, only the rest integration test +unitTest.enabled = false // no unit tests for rolling upgrades, only the rest integration test // basic integ tests includes testing bwc against the most recent version task integTest { diff --git a/x-pack/qa/rolling-upgrade/build.gradle b/x-pack/qa/rolling-upgrade/build.gradle index cabccc72cf753..0cdbbe71e55ba 100644 --- a/x-pack/qa/rolling-upgrade/build.gradle +++ b/x-pack/qa/rolling-upgrade/build.gradle @@ -7,7 +7,7 @@ import java.nio.charset.StandardCharsets // Apply the java plugin to this project so the sources can be edited in an IDE apply plugin: 'elasticsearch.standalone-test' -test.enabled = false +unitTest.enabled = false dependencies { // "org.elasticsearch.plugin:x-pack-core:${version}" doesn't work with idea because the testArtifacts are also here diff --git a/x-pack/qa/third-party/active-directory/build.gradle b/x-pack/qa/third-party/active-directory/build.gradle index 6ce8541fc431f..e33c0fa6d69f8 100644 --- a/x-pack/qa/third-party/active-directory/build.gradle +++ b/x-pack/qa/third-party/active-directory/build.gradle @@ -19,7 +19,7 @@ forbiddenPatterns { exclude '**/*.der' } -test { +unitTest { /* * We have to disable setting the number of available processors as tests in the same JVM randomize processors and will step on each * other if we allow them to set the number of available processors as it's set-once in Netty. diff --git a/x-pack/test/idp-fixture/build.gradle b/x-pack/test/idp-fixture/build.gradle index c55123e08d0f1..93f5b14ad23a2 100644 --- a/x-pack/test/idp-fixture/build.gradle +++ b/x-pack/test/idp-fixture/build.gradle @@ -1,4 +1,4 @@ apply plugin: 'elasticsearch.build' apply plugin: 'elasticsearch.test.fixtures' -test.enabled = false \ No newline at end of file +unitTest.enabled = false \ No newline at end of file diff --git a/x-pack/test/smb-fixture/build.gradle b/x-pack/test/smb-fixture/build.gradle index 5b2161de2907b..846c38829870a 100644 --- a/x-pack/test/smb-fixture/build.gradle +++ b/x-pack/test/smb-fixture/build.gradle @@ -1,4 +1,4 @@ apply plugin: 'elasticsearch.build' apply plugin: 'elasticsearch.test.fixtures' -test.enabled = false +unitTest.enabled = false