blob: 4b84f3f372e4e68c02d35931f51830d58d3e0f23 [file] [log] [blame]
// Copyright 2022 The Bazel Authors. All rights reserved.
//
// Licensed 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.google.devtools.build.lib.rules.java;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.ProviderCollection;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.TemplateVariableInfo;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.packages.Info;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.testutil.TestConstants;
import net.starlark.java.eval.EvalException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Tests for the java_runtime rule. */
@RunWith(JUnit4.class)
public class JavaRuntimeTest extends BuildViewTestCase {
@Before
public final void initializeJvmPackage() throws Exception {
scratch.file(
"jvm/BUILD",
"java_runtime(",
" name = 'jvm-k8',",
" srcs = [",
" 'k8/a', ",
" 'k8/b',",
" ], ",
" java_home = 'k8',",
")");
}
private JavaRuntimeInfo getJavaRuntimeInfo(ProviderCollection collection)
throws EvalException, RuleErrorException {
ToolchainInfo toolchainInfo = collection.get(ToolchainInfo.PROVIDER);
return JavaRuntimeInfo.PROVIDER.wrap(toolchainInfo.getValue("java_runtime", Info.class));
}
@Test
public void simple() throws Exception {
ConfiguredTarget target = getConfiguredTarget("//jvm:jvm-k8");
assertThat(ActionsTestUtil.prettyArtifactNames(getJavaRuntimeInfo(target).javaBaseInputs()))
.containsExactly("jvm/k8/a", "jvm/k8/b");
assertThat(
ActionsTestUtil.prettyArtifactNames(
target.getProvider(RunfilesProvider.class).getDataRunfiles().getArtifacts()))
.containsExactly("jvm/k8/a", "jvm/k8/b");
}
@Test
public void absoluteJavaHomeWithSrcs() throws Exception {
scratch.file("a/BUILD",
"java_runtime(name='jvm', srcs=[':dummy'], java_home='/absolute/path')");
reporter.removeHandler(failFastHandler);
getConfiguredTarget("//a:jvm");
assertContainsEvent("'java_home' with an absolute path requires 'srcs' to be empty.");
}
@Test
public void absoluteJavaHomeWithJava() throws Exception {
scratch.file(
"a/BUILD", "java_runtime(name='jvm', java='bin/java', java_home='/absolute/path')");
reporter.removeHandler(failFastHandler);
getConfiguredTarget("//a:jvm");
assertContainsEvent("'java_home' with an absolute path requires 'java' to be empty.");
}
@Test
public void binJavaPathName() throws Exception {
scratch.file("BUILD", "java_runtime(name='jvm', java='java')");
reporter.removeHandler(failFastHandler);
getConfiguredTarget("//:jvm");
assertContainsEvent("the path to 'java' must end in 'bin/java'.");
}
@Test
public void absoluteJavaHome() throws Exception {
scratch.file("a/BUILD",
"java_runtime(name='jvm', srcs=[], java_home='/absolute/path')");
reporter.removeHandler(failFastHandler);
ConfiguredTarget jvm = getConfiguredTarget("//a:jvm");
assertThat(getJavaRuntimeInfo(jvm).javaHome()).isEqualTo("/absolute/path");
}
@Test
public void relativeJavaHome() throws Exception {
scratch.file("a/BUILD",
"java_runtime(name='jvm', srcs=[], java_home='b/c')");
reporter.removeHandler(failFastHandler);
ConfiguredTarget jvm = getConfiguredTarget("//a:jvm");
assertThat(getJavaRuntimeInfo(jvm).javaHome()).isEqualTo("a/b/c");
}
@Test
public void testRuntimeAlias() throws Exception {
ConfiguredTarget reference =
scratchConfiguredTarget(
"a",
"ref",
"load('"
+ TestConstants.TOOLS_REPOSITORY
+ "//tools/jdk:java_toolchain_alias.bzl', 'java_runtime_alias')",
"java_runtime_alias(name='ref')");
assertThat(reference.get(ToolchainInfo.PROVIDER)).isNotNull();
assertThat(reference.get(TemplateVariableInfo.PROVIDER.getKey())).isNotNull();
}
@Test
public void javaHomeWithMakeVariables() throws Exception {
scratch.file("a/BUILD",
"java_runtime(name='jvm', srcs=[], java_home='/opt/$(CMDLINE)')");
useConfiguration("--define=CMDLINE=foo/bar");
ConfiguredTarget jvm = getConfiguredTarget("//a:jvm");
assertThat(getJavaRuntimeInfo(jvm).javaHome()).isEqualTo("/opt/foo/bar");
}
@Test
public void javaHomeWithInvalidMakeVariables() throws Exception {
scratch.file("a/BUILD",
"java_runtime(name='jvm', srcs=[], java_home='/opt/$(WTF)')");
reporter.removeHandler(failFastHandler);
getConfiguredTarget("//a:jvm");
assertContainsEvent("$(WTF) not defined");
}
@Test
public void makeVariables() throws Exception {
scratch.file("a/BUILD",
"java_runtime(name='jvm', srcs=[], java_home='/foo/bar')");
ImmutableMap<String, String> runtime = getConfiguredTarget("//a:jvm")
.get(TemplateVariableInfo.PROVIDER).getVariables();
assertThat(runtime.get("JAVABASE")).isEqualTo("/foo/bar");
assertThat(runtime.get("JAVA")).startsWith("/foo/bar/bin/java"); // Windows has .exe suffix
}
@Test
public void noSrcs() throws Exception {
scratch.file("a/BUILD", "java_runtime(name='jvm', java_home='/opt/jvm')");
ConfiguredTarget jvm = getConfiguredTarget("//a:jvm");
JavaRuntimeInfo provider = getJavaRuntimeInfo(jvm);
assertThat(provider.javaHome()).isEqualTo("/opt/jvm");
assertThat(provider.javaBaseInputs().toList()).isEmpty();
}
@Test
public void invalidJavaBase() throws Exception {
scratch.file(
"a/BUILD",
"java_binary(name='a', srcs=['A.java'])",
"filegroup(name='fg')",
"toolchain(",
" name = 'java_runtime_toolchain',",
" toolchain = ':fg',",
" toolchain_type = '"
+ TestConstants.TOOLS_REPOSITORY
+ "//tools/jdk:runtime_toolchain_type',",
")");
useConfiguration("--javabase=//a:fg", "--extra_toolchains=//a:all");
reporter.removeHandler(failFastHandler);
getConfiguredTarget("//a:a");
assertContainsEvent("does not provide ToolchainInfo");
}
@Test
public void javaHomeGenerated() throws Exception {
scratch.file(
"a/BUILD", //
"genrule(name='gen',",
" cmd = '', ",
" outs = ['generated_java_home/bin/java'],",
")",
"java_runtime(",
" name = 'jvm', ",
" java = 'generated_java_home/bin/java', ",
" java_home = 'generated_java_home',",
")");
ConfiguredTarget jvm = getConfiguredTarget("//a:jvm");
assertThat(getJavaRuntimeInfo(jvm).javaHome())
.isEqualTo(getGenfilesArtifactWithNoOwner("a/generated_java_home").getExecPathString());
}
// bypass default toolchain flags added by BuildViewTestCase#useConfiguration
// TODO(cushon): delete this helper method once useConfiguration stops passing toolchain flags
private void useConfigurationInternal(String... args) throws Exception {
targetConfig = createConfiguration(ImmutableMap.of(), args);
targetConfigKey = targetConfig.getKey();
createBuildView();
}
@Test
public void disallowLegacyJavabaseFlag() {
InvalidConfigurationException e =
assertThrows(
InvalidConfigurationException.class,
() ->
useConfigurationInternal(
"--experimental_disallow_legacy_java_toolchain_flags",
"--javabase=//no/such:label"));
assertThat(e).hasMessageThat().contains("--javabase=//no/such:label is no longer supported");
}
@Test
public void disallowLegacyHostJavabaseFlagbaseFlag() {
InvalidConfigurationException e =
assertThrows(
InvalidConfigurationException.class,
() ->
useConfigurationInternal(
"--experimental_disallow_legacy_java_toolchain_flags",
"--host_javabase=//no/such:label"));
assertThat(e)
.hasMessageThat()
.contains("--host_javabase=//no/such:label is no longer supported");
}
@Test
public void disallowLegacyJavabaseFlag_unset() throws Exception {
scratch.file(
"a/defs.bzl",
"def _ht(settings, attrs):",
" return {",
" '//command_line_option:javabase': '//tools/jdk:jdk',",
" '//command_line_option:host_javabase': '//tools/jdk:remote_jdk11',",
" '//command_line_option:java_toolchain': '//tools/jdk:remote_toolchain',",
" '//command_line_option:host_java_toolchain': '//tools/jdk:remote_toolchain',",
" }",
"",
"ht = transition(",
" implementation = _ht,",
" inputs = [",
" '//command_line_option:javabase',",
" '//command_line_option:host_javabase',",
" '//command_line_option:java_toolchain',",
" '//command_line_option:host_java_toolchain',",
" ],",
" outputs = [",
" '//command_line_option:javabase',",
" '//command_line_option:host_javabase',",
" '//command_line_option:java_toolchain',",
" '//command_line_option:host_java_toolchain',",
" ],",
")",
"",
"def _r(ctx):",
" return [DefaultInfo(files = ctx.attr.d[0].files)]",
"",
"r = rule(",
" attrs = {",
" 'd': attr.label(",
" cfg = ht,",
" mandatory = True,",
" ),",
" '_allowlist_function_transition': attr.label(",
" default = '//tools/allowlists/function_transition_allowlist',",
" ),",
" },",
" implementation = _r,",
")");
scratch.overwriteFile(
"tools/allowlists/function_transition_allowlist/BUILD",
"package_group(",
" name = 'function_transition_allowlist',",
" packages = ['//...'],",
")",
"filegroup(",
" name = 'srcs',",
" srcs = glob(['**']),",
" visibility = ['//tools/allowlists:__pkg__'],",
")");
scratch.file(
"a/BUILD", //
"load(':defs.bzl', 'r')",
"java_binary(name = 'd', main_class = 'D')",
"r(name = 't', d = ':d')");
useConfiguration("--experimental_disallow_legacy_java_toolchain_flags");
reporter.removeHandler(failFastHandler);
getConfiguredTarget("//a:t");
assertContainsEvent("--javabase=//tools/jdk:jdk is no longer supported");
}
}