org.opensearch.gradle.OpenSearchTestBasePlugin Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of build-tools Show documentation
Show all versions of build-tools Show documentation
OpenSearch subproject :build-tools
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
/*
* 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.
*/
/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.gradle;
import com.github.jengelman.gradle.plugins.shadow.ShadowBasePlugin;
import org.opensearch.gradle.info.BuildParams;
import org.opensearch.gradle.info.GlobalBuildInfoPlugin;
import org.opensearch.gradle.jvm.JvmTestSuiteHelper;
import org.opensearch.gradle.test.ErrorReportingTestListener;
import org.opensearch.gradle.util.Util;
import org.gradle.api.Action;
import org.gradle.api.JavaVersion;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.FileCollection;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.testing.Test;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import static org.opensearch.gradle.util.FileUtils.mkdirs;
import static org.opensearch.gradle.util.GradleUtils.maybeConfigure;
/**
* Applies commonly used settings to all Test tasks in the project
*/
public class OpenSearchTestBasePlugin implements Plugin {
@Override
public void apply(Project project) {
// for fips mode check
project.getRootProject().getPluginManager().apply(GlobalBuildInfoPlugin.class);
// Default test task should run only unit tests
maybeConfigure(project.getTasks(), "test", Test.class, task -> task.include("**/*Tests.class"));
// none of this stuff is applicable to the `:buildSrc` project tests
if (project.getPath().equals(":build-tools")) {
return;
}
File heapdumpDir = new File(project.getBuildDir(), "heapdump");
project.getTasks().withType(Test.class).configureEach(test -> {
File testOutputDir = new File(test.getReports().getJunitXml().getOutputLocation().getAsFile().get(), "output");
ErrorReportingTestListener listener = new ErrorReportingTestListener(test.getTestLogging(), test.getLogger(), testOutputDir);
test.getExtensions().add("errorReportingTestListener", listener);
test.addTestOutputListener(listener);
test.addTestListener(listener);
/*
* 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.
*/
SystemPropertyCommandLineArgumentProvider nonInputProperties = new SystemPropertyCommandLineArgumentProvider();
// We specifically use an anonymous inner class here because lambda task actions break Gradle cacheability
// See: https://docs.gradle.org/current/userguide/more_about_tasks.html#sec:how_does_it_work
test.doFirst(new Action() {
@Override
public void execute(Task t) {
mkdirs(testOutputDir);
mkdirs(heapdumpDir);
mkdirs(test.getWorkingDir());
mkdirs(test.getWorkingDir().toPath().resolve("temp").toFile());
// TODO remove once jvm.options are added to test system properties
if (BuildParams.getRuntimeJavaVersion() == JavaVersion.VERSION_1_8) {
test.systemProperty("java.locale.providers", "SPI,JRE");
} else {
test.systemProperty("java.locale.providers", "SPI,COMPAT");
if (test.getJavaVersion().compareTo(JavaVersion.VERSION_17) < 0) {
test.jvmArgs("--illegal-access=warn");
}
}
if (test.getJavaVersion().compareTo(JavaVersion.VERSION_17) > 0) {
test.jvmArgs("-Djava.security.manager=allow");
}
}
});
test.getJvmArgumentProviders().add(nonInputProperties);
test.getExtensions().add("nonInputProperties", nonInputProperties);
test.setWorkingDir(project.file(project.getBuildDir() + "/testrun/" + test.getName()));
test.setMaxParallelForks(Integer.parseInt(System.getProperty("tests.jvms", BuildParams.getDefaultParallel().toString())));
test.exclude("**/*$*.class");
test.jvmArgs(
"-Xmx" + System.getProperty("tests.heap.size", "512m"),
"-Xms" + System.getProperty("tests.heap.size", "512m"),
"-XX:+HeapDumpOnOutOfMemoryError"
);
test.getJvmArgumentProviders().add(new SimpleCommandLineArgumentProvider("-XX:HeapDumpPath=" + heapdumpDir));
String argline = System.getProperty("tests.jvm.argline");
if (argline != null) {
test.jvmArgs((Object[]) argline.split(" "));
}
if (Util.getBooleanProperty("tests.asserts", true)) {
test.jvmArgs("-ea", "-esa");
}
Map sysprops = new HashMap() {
{
put("java.awt.headless", "true");
put("tests.gradle", "true");
put("tests.artifact", project.getName());
put("tests.task", test.getPath());
put("tests.security.manager", "true");
put("jna.nosys", "true");
}
};
test.systemProperties(sysprops);
// ignore changing test seed when build is passed -Dignore.tests.seed for cacheability experimentation
if (System.getProperty("ignore.tests.seed") != null) {
nonInputProperties.systemProperty("tests.seed", BuildParams.getTestSeed());
} else {
test.systemProperty("tests.seed", BuildParams.getTestSeed());
}
// don't track these as inputs since they contain absolute paths and break cache relocatability
File gradleHome = project.getGradle().getGradleUserHomeDir();
String gradleVersion = project.getGradle().getGradleVersion();
nonInputProperties.systemProperty("gradle.dist.lib", new File(project.getGradle().getGradleHomeDir(), "lib"));
nonInputProperties.systemProperty(
"gradle.worker.jar",
gradleHome + "/caches/" + gradleVersion + "/workerMain/gradle-worker.jar"
);
nonInputProperties.systemProperty("gradle.user.home", gradleHome);
// we use 'temp' relative to CWD since this is per JVM and tests are forbidden from writing to CWD
nonInputProperties.systemProperty("java.io.tmpdir", test.getWorkingDir().toPath().resolve("temp"));
// TODO: remove setting logging level via system property
test.systemProperty("tests.logger.level", "WARN");
System.getProperties().entrySet().forEach(entry -> {
if ((entry.getKey().toString().startsWith("tests.") || entry.getKey().toString().startsWith("opensearch."))) {
test.systemProperty(entry.getKey().toString(), entry.getValue());
}
});
// TODO: remove this once ctx isn't added to update script params in 7.0
test.systemProperty("opensearch.scripting.update.ctx_in_params", "false");
// TODO: remove this property in 8.0
test.systemProperty("opensearch.search.rewrite_sort", "true");
// TODO: remove this once cname is prepended to transport.publish_address by default in 8.0
test.systemProperty("opensearch.transport.cname_in_publish_address", "true");
// Set netty system properties to the properties we configure in jvm.options
test.systemProperty("io.netty.noUnsafe", "true");
test.systemProperty("io.netty.noKeySetOptimization", "true");
test.systemProperty("io.netty.recycler.maxCapacityPerThread", "0");
test.testLogging(logging -> {
logging.setShowExceptions(true);
logging.setShowCauses(true);
logging.setExceptionFormat("full");
logging.setShowStandardStreams(Util.getBooleanProperty("tests.output", false));
});
if (OS.current().equals(OS.WINDOWS) && System.getProperty("tests.timeoutSuite") == null) {
// override the suite timeout to 30 mins for windows, because it has the most inefficient filesystem known to man
test.systemProperty("tests.timeoutSuite", "1800000!");
}
/*
* If this project builds a shadow JAR than any unit tests should test against that artifact instead of
* compiled class output and dependency jars. This better emulates the runtime environment of consumers.
*/
project.getPluginManager().withPlugin("com.github.johnrengelman.shadow", p -> {
// Remove output class files and any other dependencies from the test classpath, since the shadow JAR includes these
FileCollection mainRuntime = project.getExtensions()
.getByType(SourceSetContainer.class)
.getByName(SourceSet.MAIN_SOURCE_SET_NAME)
.getRuntimeClasspath();
// Add any "shadow" dependencies. These are dependencies that are *not* bundled into the shadow JAR
Configuration shadowConfig = project.getConfigurations().getByName(ShadowBasePlugin.CONFIGURATION_NAME);
// Add the shadow JAR artifact itself
FileCollection shadowJar = project.files(project.getTasks().named("shadowJar"));
// See please https://docs.gradle.org/8.1/userguide/upgrading_version_8.html#test_task_default_classpath
test.setClasspath(
JvmTestSuiteHelper.getDefaultTestSuite(project)
.map(suite -> suite.getSources().getRuntimeClasspath())
.orElseGet(() -> test.getClasspath())
.minus(mainRuntime)
.plus(shadowConfig)
.plus(shadowJar)
);
});
});
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy