| // Copyright 2021 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.view.java; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| import static com.google.common.truth.Truth.assertWithMessage; |
| import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.prettyArtifactNames; |
| import static com.google.devtools.build.lib.rules.java.JavaCompileActionTestHelper.getProcessorpath; |
| |
| import com.google.devtools.build.lib.actions.Artifact; |
| import com.google.devtools.build.lib.actions.util.ActionsTestUtil; |
| import com.google.devtools.build.lib.analysis.ConfiguredTarget; |
| import com.google.devtools.build.lib.analysis.OutputGroupInfo; |
| import com.google.devtools.build.lib.analysis.actions.SpawnAction; |
| import com.google.devtools.build.lib.analysis.configuredtargets.FileConfiguredTarget; |
| import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; |
| import com.google.devtools.build.lib.collect.nestedset.NestedSet; |
| import com.google.devtools.build.lib.rules.java.JavaCompileAction; |
| import com.google.devtools.build.lib.rules.java.JavaPluginInfo; |
| import com.google.devtools.build.lib.rules.java.ProguardSpecProvider; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.JUnit4; |
| |
| /** Unit tests for java_plugin rule. */ |
| @RunWith(JUnit4.class) |
| public class JavaPluginConfiguredTargetTest extends BuildViewTestCase { |
| |
| @Test |
| public void testNoConstraintsAttribute() throws Exception { |
| checkError( |
| "java/plugin", |
| "plugin", |
| "no such attribute 'constraints' in 'java_plugin'", |
| "java_plugin(name = 'plugin',", |
| " srcs = ['A.java'],", |
| " processor_class = 'xx',", |
| " constraints = ['this_shouldnt_exist'])"); |
| } |
| |
| private void setupEmptyProcessorClass() throws Exception { |
| scratch.file( |
| "java/com/google/test/BUILD", |
| "java_library(name = 'deps',", |
| " srcs = ['Deps.java'])", |
| "java_plugin(name = 'processor',", |
| " processor_class = 'com.google.test.Processor',", |
| " srcs = ['Processor.java'],", |
| " deps = [':deps'])", |
| "java_plugin(name = 'bugchecker',", |
| " srcs = ['BugChecker.java'],", |
| " deps = [':deps'])", |
| "java_library(name = 'empty',", |
| " plugins = [':bugchecker'])"); |
| } |
| |
| @Test |
| public void testNotEmptyProcessorClass() throws Exception { |
| setupEmptyProcessorClass(); |
| |
| ConfiguredTarget processorTarget = getConfiguredTarget("//java/com/google/test:processor"); |
| assertThat(processorTarget.get(JavaPluginInfo.PROVIDER).plugins().processorClasses().toList()) |
| .containsExactly("com.google.test.Processor"); |
| assertThat( |
| prettyArtifactNames( |
| processorTarget.get(JavaPluginInfo.PROVIDER).plugins().processorClasspath())) |
| .containsExactly( |
| "java/com/google/test/libprocessor.jar", "java/com/google/test/libdeps.jar"); |
| } |
| |
| @Test |
| public void testEmptyProcessorClass() throws Exception { |
| setupEmptyProcessorClass(); |
| |
| ConfiguredTarget bugcheckerTarget = getConfiguredTarget("//java/com/google/test:bugchecker"); |
| assertThat(bugcheckerTarget.get(JavaPluginInfo.PROVIDER).plugins().processorClasses().toList()) |
| .isEmpty(); |
| |
| assertThat( |
| prettyArtifactNames( |
| bugcheckerTarget.get(JavaPluginInfo.PROVIDER).plugins().processorClasspath())) |
| .containsExactly( |
| "java/com/google/test/libbugchecker.jar", "java/com/google/test/libdeps.jar"); |
| } |
| |
| @Test |
| public void testEmptyProcessorClassTarget() throws Exception { |
| setupEmptyProcessorClass(); |
| ConfiguredTarget bugcheckerTarget = getConfiguredTarget("//java/com/google/test:bugchecker"); |
| FileConfiguredTarget emptyOutput = |
| getFileConfiguredTarget("//java/com/google/test:libempty.jar"); |
| JavaCompileAction javacAction = |
| (JavaCompileAction) getGeneratingAction(emptyOutput.getArtifact()); |
| assertThat( |
| Artifact.toRootRelativePaths( |
| bugcheckerTarget |
| .get(JavaPluginInfo.PROVIDER) |
| .plugins() |
| .processorClasspath() |
| .toList())) |
| .containsExactlyElementsIn( |
| Artifact.toRootRelativePaths(getInputs(javacAction, getProcessorpath(javacAction)))); |
| } |
| |
| @Test |
| public void testJavaPluginExportsTransitiveProguardSpecs() throws Exception { |
| scratch.file( |
| "java/com/google/android/hello/BUILD", |
| "java_plugin(name = 'plugin',", |
| " srcs = ['Plugin.java'],", |
| " proguard_specs = ['plugin.pro'])", |
| "java_library(name = 'dep',", |
| " srcs = ['Dep.java'],", |
| " proguard_specs = ['dep.pro'])", |
| "java_plugin(name = 'top',", |
| " srcs = ['Top.java'],", |
| " proguard_specs = ['top.pro'],", |
| " plugins = [':plugin'],", |
| " deps = [':dep'])"); |
| NestedSet<Artifact> providedSpecs = |
| getConfiguredTarget("//java/com/google/android/hello:top") |
| .get(ProguardSpecProvider.PROVIDER) |
| .getTransitiveProguardSpecs(); |
| assertThat(ActionsTestUtil.baseArtifactNames(providedSpecs)) |
| .containsAtLeast("top.pro_valid", "dep.pro_valid"); |
| assertThat(ActionsTestUtil.baseArtifactNames(providedSpecs)).doesNotContain("plugin.pro_valid"); |
| } |
| |
| @Test |
| public void testJavaPluginValidatesProguardSpecs() throws Exception { |
| scratch.file( |
| "java/com/google/android/hello/BUILD", |
| "java_plugin(name = 'plugin',", |
| " srcs = ['Plugin.java'],", |
| " proguard_specs = ['plugin.pro'])"); |
| SpawnAction action = |
| (SpawnAction) |
| actionsTestUtil() |
| .getActionForArtifactEndingWith( |
| getOutputGroup( |
| getConfiguredTarget("//java/com/google/android/hello:plugin"), |
| OutputGroupInfo.HIDDEN_TOP_LEVEL), |
| "plugin.pro_valid"); |
| assertWithMessage("Proguard validate action").that(action).isNotNull(); |
| assertWithMessage("Proguard validate action input") |
| .that(prettyArtifactNames(action.getInputs())) |
| .contains("java/com/google/android/hello/plugin.pro"); |
| } |
| |
| @Test |
| public void testJavaPluginValidatesTransitiveProguardSpecs() throws Exception { |
| scratch.file( |
| "java/com/google/android/hello/BUILD", |
| "java_library(name = 'transitive',", |
| " srcs = ['Transitive.java'],", |
| " proguard_specs = ['transitive.pro'])", |
| "java_plugin(name = 'plugin',", |
| " srcs = ['Plugin.java'],", |
| " deps = [':transitive'])"); |
| SpawnAction action = |
| (SpawnAction) |
| actionsTestUtil() |
| .getActionForArtifactEndingWith( |
| getOutputGroup( |
| getConfiguredTarget("//java/com/google/android/hello:plugin"), |
| OutputGroupInfo.HIDDEN_TOP_LEVEL), |
| "transitive.pro_valid"); |
| assertWithMessage("Proguard validate action").that(action).isNotNull(); |
| assertWithMessage("Proguard validate action input") |
| .that(prettyArtifactNames(action.getInputs())) |
| .contains("java/com/google/android/hello/transitive.pro"); |
| } |
| |
| @Test |
| public void generatesApi() throws Exception { |
| scratch.file( |
| "java/com/google/test/BUILD", |
| "java_plugin(", |
| " name = 'api_generating',", |
| " srcs = ['ApiGeneratingPlugin.java'],", |
| " processor_class = 'ApiGeneratingPlugin',", |
| " generates_api = True,", |
| ")"); |
| |
| JavaPluginInfo plugin = |
| getConfiguredTarget("//java/com/google/test:api_generating").get(JavaPluginInfo.PROVIDER); |
| assertThat(plugin.plugins().processorClasses().toList()).containsExactly("ApiGeneratingPlugin"); |
| assertThat(plugin.apiGeneratingPlugins().processorClasses().toList()) |
| .containsExactly("ApiGeneratingPlugin"); |
| assertThat(ActionsTestUtil.baseArtifactNames(plugin.plugins().processorClasspath())) |
| .containsExactly("libapi_generating.jar"); |
| assertThat( |
| ActionsTestUtil.baseArtifactNames(plugin.apiGeneratingPlugins().processorClasspath())) |
| .containsExactly("libapi_generating.jar"); |
| } |
| |
| @Test |
| public void generatesImplementation() throws Exception { |
| scratch.file( |
| "java/com/google/test/BUILD", |
| "java_plugin(", |
| " name = 'impl_generating',", |
| " srcs = ['ImplGeneratingPlugin.java'],", |
| " processor_class = 'ImplGeneratingPlugin',", |
| " generates_api = False,", |
| ")"); |
| |
| JavaPluginInfo plugin = |
| getConfiguredTarget("//java/com/google/test:impl_generating").get(JavaPluginInfo.PROVIDER); |
| assertThat(plugin.plugins().processorClasses().toList()) |
| .containsExactly("ImplGeneratingPlugin"); |
| assertThat(plugin.apiGeneratingPlugins().processorClasses().toList()).isEmpty(); |
| assertThat(ActionsTestUtil.baseArtifactNames(plugin.plugins().processorClasspath())) |
| .containsExactly("libimpl_generating.jar"); |
| assertThat( |
| ActionsTestUtil.baseArtifactNames(plugin.apiGeneratingPlugins().processorClasspath())) |
| .isEmpty(); |
| } |
| |
| @Test |
| public void pluginData() throws Exception { |
| scratch.file( |
| "java/com/google/test/BUILD", |
| "java_plugin(", |
| " name = 'impl_generating',", |
| " srcs = ['ImplGeneratingPlugin.java'],", |
| " processor_class = 'ImplGeneratingPlugin',", |
| " generates_api = False,", |
| " data = ['data.txt'],", |
| ")", |
| "java_library(", |
| " name = 'lib',", |
| " plugins = [':impl_generating'],", |
| ")"); |
| |
| JavaPluginInfo plugin = |
| getConfiguredTarget("//java/com/google/test:impl_generating").get(JavaPluginInfo.PROVIDER); |
| assertThat(prettyArtifactNames(plugin.plugins().data())) |
| .containsExactly("java/com/google/test/data.txt"); |
| FileConfiguredTarget libJar = getFileConfiguredTarget("//java/com/google/test:liblib.jar"); |
| JavaCompileAction javacAction = (JavaCompileAction) getGeneratingAction(libJar.getArtifact()); |
| assertThat(prettyArtifactNames(javacAction.getInputs())) |
| .contains("java/com/google/test/data.txt"); |
| } |
| } |