| // 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"); |
| } |
| } |