mirror of https://github.com/apache/lucene.git
287 lines
13 KiB
Groovy
287 lines
13 KiB
Groovy
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF 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.
|
|
*/
|
|
|
|
//
|
|
// Configure test randomization seeds and derived test properties.
|
|
//
|
|
|
|
import java.nio.file.*
|
|
import com.carrotsearch.randomizedtesting.SeedUtils
|
|
import com.carrotsearch.randomizedtesting.generators.RandomPicks
|
|
import org.apache.tools.ant.types.Commandline
|
|
|
|
buildscript {
|
|
repositories {
|
|
mavenCentral()
|
|
}
|
|
|
|
dependencies {
|
|
classpath deps.randomizedtesting.runner
|
|
}
|
|
}
|
|
|
|
def resources = scriptResources(buildscript)
|
|
|
|
// Pick the "root" seed from which everything else is derived.
|
|
configure(rootProject) {
|
|
ext {
|
|
rootSeed = propertyOrDefault('tests.seed', String.format("%08X", new Random().nextLong()))
|
|
rootSeedUserProvided = (propertyOrDefault('tests.seed', null) != null)
|
|
rootSeedLong = SeedUtils.parseSeedChain(rootSeed)[0]
|
|
projectSeedLong = rootSeedLong ^ project.path.hashCode()
|
|
}
|
|
|
|
task randomizationInfo() {
|
|
doFirst {
|
|
logger.lifecycle("Running tests with randomization seed: tests.seed=${rootSeed}")
|
|
}
|
|
}
|
|
}
|
|
|
|
// Any test task will trigger display of randomization settings.
|
|
allprojects {
|
|
tasks.withType(Test) { task ->
|
|
task.dependsOn rootProject.randomizationInfo
|
|
}
|
|
}
|
|
|
|
// Configure test property defaults and their descriptions.
|
|
allprojects {
|
|
plugins.withType(JavaPlugin) {
|
|
project.ext {
|
|
String randomVectorSize = RandomPicks.randomFrom(new Random(projectSeedLong), ["default", "128", "256", "512"])
|
|
testOptions += [
|
|
// seed, repetition and amplification.
|
|
[propName: 'tests.seed', value: { -> rootSeed }, description: "Sets the master randomization seed."],
|
|
[propName: 'tests.iters', value: null, description: "Duplicate (re-run) each test case N times."],
|
|
[propName: 'tests.multiplier', value: null, description: "Value multiplier for randomized tests."],
|
|
[propName: 'tests.maxfailures', value: null, description: "Skip tests after a given number of failures."],
|
|
[propName: 'tests.timeoutSuite', value: null, description: "Timeout (in millis) for an entire suite."],
|
|
[propName: 'tests.failfast', value: "false", description: "Stop the build early on failure.", buildOnly: true],
|
|
// asserts, debug output.
|
|
[propName: 'tests.asserts', value: "true", description: "Enables or disables assertions mode."],
|
|
[propName: 'tests.infostream', value: false, description: "Enables or disables infostream logs."],
|
|
[propName: 'tests.leaveTemporary', value: false, description: "Leave temporary directories after tests complete."],
|
|
[propName: 'tests.useSecurityManager', value: true, description: "Control security manager in tests.", buildOnly: true],
|
|
// component randomization
|
|
[propName: 'tests.codec', value: "random", description: "Sets the codec tests should run with."],
|
|
[propName: 'tests.directory', value: "random", description: "Sets the Directory implementation tests should run with."],
|
|
[propName: 'tests.postingsformat', value: "random", description: "Sets the postings format tests should run with."],
|
|
[propName: 'tests.docvaluesformat', value: "random", description: "Sets the doc values format tests should run with."],
|
|
[propName: 'tests.locale', value: "random", description: "Sets the default locale tests should run with."],
|
|
[propName: 'tests.timezone', value: "random", description: "Sets the default time zone tests should run with."],
|
|
// filtering
|
|
[propName: 'tests.filter', value: null, description: "Applies a test filter (see :helpTests)."],
|
|
[propName: 'tests.nightly', value: false, description: "Enables or disables @Nightly tests."],
|
|
[propName: 'tests.weekly', value: false, description: "Enables or disables @Weekly tests."],
|
|
[propName: 'tests.monster', value: false, description: "Enables or disables @Monster tests."],
|
|
[propName: 'tests.awaitsfix', value: null, description: "Enables or disables @AwaitsFix tests."],
|
|
[propName: 'tests.gui',
|
|
value: { ->
|
|
return rootProject.ext.isCIBuild
|
|
},
|
|
description: "Enables or disables @RequiresGUI tests."],
|
|
[propName: 'tests.file.encoding',
|
|
value: { ->
|
|
RandomPicks.randomFrom(new Random(projectSeedLong), ["US-ASCII", "ISO-8859-1", "UTF-8"])
|
|
},
|
|
description: "Sets the default file.encoding on test JVM.", buildOnly: true],
|
|
// Test data file used.
|
|
[propName: 'tests.linedocsfile', value: 'europarl.lines.txt.gz', description: "Test data file path."],
|
|
// miscellaneous; some of them very weird.
|
|
[propName: 'tests.LUCENE_VERSION', value: baseVersion, description: "Base Lucene version."],
|
|
[propName: 'tests.bwcdir', value: null, description: "Data for backward-compatibility indexes."],
|
|
// vectorization related
|
|
[propName: 'tests.vectorsize',
|
|
value: { -> testsDefaultVectorizationRequested() ? 'default' : randomVectorSize },
|
|
description: "Sets preferred vector size in bits."],
|
|
[propName: 'tests.forceintegervectors',
|
|
value: { -> testsDefaultVectorizationRequested() ? false : (randomVectorSize != 'default') },
|
|
description: "Forces use of integer vectors even when slow."],
|
|
[propName: 'tests.defaultvectorization', value: false,
|
|
description: "Uses defaults for running tests with correct JVM settings to test Panama vectorization (tests.jvmargs, tests.vectorsize, tests.forceintegervectors)."],
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
// Resolve test option values after all evaluation is complete.
|
|
allprojects {
|
|
plugins.withType(JavaPlugin) {
|
|
configurations {
|
|
secManagerExclusions
|
|
}
|
|
dependencies {
|
|
secManagerExclusions ( deps.randomizedtesting.runner, {
|
|
exclude group: "junit"
|
|
})
|
|
secManagerExclusions ( deps.junit, {
|
|
exclude group: "org.hamcrest"
|
|
})
|
|
}
|
|
|
|
afterEvaluate {
|
|
project.ext.testOptionsResolved = testOptions.findAll { opt ->
|
|
propertyOrDefault(opt.propName, opt.value) != null
|
|
}.collectEntries { opt ->
|
|
[(opt.propName): Objects.toString(resolvedTestOption(opt.propName))]
|
|
}
|
|
|
|
// Compute the "reproduce with" string.
|
|
project.ext.testOptionsForReproduceLine = testOptions.findAll { opt ->
|
|
if (opt["includeInReproLine"] == false) {
|
|
return false
|
|
}
|
|
|
|
def defValue = Objects.toString(opt.value, null)
|
|
def value = testOptionsResolved[opt.propName]
|
|
return defValue != value
|
|
}.collect { opt ->
|
|
Commandline.quoteArgument("-P" + opt.propName + "=" + testOptionsResolved[opt.propName])
|
|
}.join(" ")
|
|
|
|
// leaving temporary folder option has multiple aliases...
|
|
if ([
|
|
"tests.leaveTemporary",
|
|
"tests.leavetemporary",
|
|
"tests.leavetmpdir",
|
|
].find { prop ->
|
|
def v = Boolean.parseBoolean(propertyOrDefault(prop, "false"))
|
|
if (v) {
|
|
logger.lifecycle("Update your code to use the official 'tests.leaveTemporary' option (you used '${prop}').")
|
|
}
|
|
return v
|
|
}) {
|
|
testOptionsResolved['tests.leaveTemporary'] = "true"
|
|
}
|
|
|
|
// Append resolved test properties to the test task.
|
|
tasks.withType(Test) { Test task ->
|
|
// TODO: we could remove some options that are only relevant to the build environment
|
|
// and not the test JVM itself.
|
|
systemProperties testOptionsResolved
|
|
|
|
jvmArgs Commandline.translateCommandline(testOptionsResolved['tests.jvmargs'])
|
|
|
|
if (Boolean.parseBoolean(testOptionsResolved['tests.asserts'])) {
|
|
jvmArgs("-ea", "-esa")
|
|
} else {
|
|
enableAssertions = false
|
|
}
|
|
|
|
if (Boolean.parseBoolean(testOptionsResolved["tests.failfast"])) {
|
|
failFast true
|
|
}
|
|
|
|
// Enable security manager, if requested. We could move the selection of security manager and security policy
|
|
// to each project's build/ configuration but it seems compact enough to keep it here for now.
|
|
def securityArgumentProvider = new SecurityArgumentProvider()
|
|
securityArgumentProvider.commonDir = project(":lucene").layout.projectDirectory
|
|
securityArgumentProvider.otherProperties = project.objects.mapProperty(String, String)
|
|
|
|
if (Boolean.parseBoolean(testOptionsResolved["tests.useSecurityManager"])) {
|
|
if (project.path.endsWith(".tests")) {
|
|
// LUCENE-10301: for now, do not use the security manager for modular tests (test framework is not available).
|
|
} else if (project.path.startsWith(":lucene")) {
|
|
systemProperty 'java.security.manager', "org.apache.lucene.tests.util.TestSecurityManager"
|
|
securityArgumentProvider.javaSecurityPolicy = layout.projectDirectory.file("${resources}/policies/tests.policy")
|
|
}
|
|
jvmArgumentProviders.add(securityArgumentProvider)
|
|
|
|
def gradleUserHome = project.gradle.getGradleUserHomeDir()
|
|
systemProperty 'gradle.lib.dir', Paths.get(project.class.location.toURI()).parent.toAbsolutePath().toString().replace('\\', '/')
|
|
systemProperty 'gradle.worker.jar', Paths.get("${gradleUserHome}/caches/${gradle.gradleVersion}/workerMain/gradle-worker.jar").toAbsolutePath().toString()
|
|
systemProperty 'gradle.user.home', gradleUserHome.toPath().toAbsolutePath().toString()
|
|
|
|
securityArgumentProvider.otherProperties.put("randomizedtesting.jar", project.provider { ->
|
|
return configurations.secManagerExclusions.resolve().find { it.name.startsWith("randomizedtesting-runner-") }.absolutePath
|
|
})
|
|
securityArgumentProvider.otherProperties.put("junit.jar", project.provider { ->
|
|
return configurations.secManagerExclusions.resolve().find { it.name.startsWith("junit-") }.absolutePath
|
|
})
|
|
securityArgumentProvider.otherProperties.put("lucene.test.framework", project(":lucene:test-framework").layout.buildDirectory.get().asFile.absolutePath)
|
|
}
|
|
|
|
doFirst {
|
|
logger.debug("Will use test opts:\n" + testOptionsResolved.collect {k,v -> "${k}: ${v}"}.sort().join("\n"))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add a helper task to display resolved test property values with their defaults
|
|
// and descriptions.
|
|
allprojects {
|
|
plugins.withType(JavaPlugin) {
|
|
task testOpts() {
|
|
group = 'Help (developer guides and hints)'
|
|
description = "Display values of randomization settings for a given seed"
|
|
|
|
doFirst {
|
|
println "Test options for project ${project.path} and seed \"${rootSeed}\":"
|
|
|
|
testOptions.sort { a, b -> a.propName.compareTo(b.propName) }.each { opt ->
|
|
def defValue
|
|
def computedValue = false
|
|
if (opt.value instanceof Closure) {
|
|
defValue = Objects.toString(opt.value(), null)
|
|
computedValue = true
|
|
} else {
|
|
defValue = Objects.toString(opt.value, null)
|
|
}
|
|
|
|
def value = testOptionsResolved[opt.propName]
|
|
println String.format(Locale.ROOT,
|
|
"%s%-24s = %-8s # %s",
|
|
(defValue != value ? "! " : computedValue ? "C " : " "),
|
|
opt.propName,
|
|
value,
|
|
(computedValue ? "(!= default: computed) " : (defValue != value ? "(!= default: ${defValue}) " : "")) + opt.description)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
class SecurityArgumentProvider implements CommandLineArgumentProvider {
|
|
@Internal
|
|
Directory commonDir
|
|
|
|
@InputFile
|
|
@Optional
|
|
@PathSensitive(PathSensitivity.RELATIVE)
|
|
RegularFile javaSecurityPolicy
|
|
|
|
@Input
|
|
MapProperty<String, String> otherProperties
|
|
|
|
@Override
|
|
Iterable<String> asArguments() {
|
|
def args = ["-Dcommon.dir=${commonDir.getAsFile()}"]
|
|
if (javaSecurityPolicy) {
|
|
args.add("-Djava.security.policy=${javaSecurityPolicy.getAsFile()}")
|
|
}
|
|
|
|
otherProperties.getOrElse(Map.of()).forEach { key, value ->
|
|
args.add("-D${key}=${value}")
|
|
}
|
|
|
|
return args
|
|
}
|
|
}
|