| // Copyright 2017 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.bazel.rules.android; |
| |
| import static com.google.devtools.build.lib.packages.Attribute.attr; |
| import static com.google.devtools.build.lib.packages.BuildType.LABEL; |
| import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; |
| import static com.google.devtools.build.lib.packages.BuildType.TRISTATE; |
| import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.fromFunctions; |
| |
| import com.google.common.collect.ImmutableCollection; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.devtools.build.lib.analysis.BaseRuleClasses; |
| import com.google.devtools.build.lib.analysis.RuleDefinition; |
| import com.google.devtools.build.lib.analysis.RuleDefinitionEnvironment; |
| import com.google.devtools.build.lib.bazel.rules.java.BazelJavaRuleClasses.BaseJavaBinaryRule; |
| import com.google.devtools.build.lib.packages.ImplicitOutputsFunction; |
| import com.google.devtools.build.lib.packages.RuleClass; |
| import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; |
| import com.google.devtools.build.lib.packages.SkylarkProviderIdentifier; |
| import com.google.devtools.build.lib.packages.TriState; |
| import com.google.devtools.build.lib.rules.android.AndroidFeatureFlagSetProvider; |
| import com.google.devtools.build.lib.rules.android.AndroidLocalTestBaseRule; |
| import com.google.devtools.build.lib.rules.config.ConfigFeatureFlagTransitionFactory; |
| import com.google.devtools.build.lib.rules.cpp.CppRuleClasses; |
| import com.google.devtools.build.lib.rules.java.JavaConfiguration; |
| import com.google.devtools.build.lib.rules.java.JavaInfo; |
| import com.google.devtools.build.lib.rules.java.JavaSemantics; |
| |
| /** Rule definition for Bazel android_local_test */ |
| public class BazelAndroidLocalTestRule implements RuleDefinition { |
| |
| protected static final String JUNIT_TESTRUNNER = "//tools/jdk:TestRunner_deploy.jar"; |
| |
| private static final ImmutableCollection<String> ALLOWED_RULES_IN_DEPS = |
| ImmutableSet.of( |
| "aar_import", |
| "android_library", |
| "java_import", |
| "java_library", |
| "java_lite_proto_library"); |
| |
| static final ImplicitOutputsFunction ANDROID_ROBOLECTRIC_IMPLICIT_OUTPUTS = fromFunctions( |
| JavaSemantics.JAVA_BINARY_CLASS_JAR, |
| JavaSemantics.JAVA_BINARY_SOURCE_JAR, |
| JavaSemantics.JAVA_BINARY_DEPLOY_JAR); |
| |
| @Override |
| public RuleClass build(RuleClass.Builder builder, RuleDefinitionEnvironment environment) { |
| return builder |
| .requiresConfigurationFragments(JavaConfiguration.class) |
| .setImplicitOutputsFunction(ANDROID_ROBOLECTRIC_IMPLICIT_OUTPUTS) |
| .override( |
| attr("deps", LABEL_LIST) |
| .allowedFileTypes() |
| .allowedRuleClasses(ALLOWED_RULES_IN_DEPS) |
| .mandatoryProvidersList( |
| ImmutableList.of( |
| ImmutableList.of( |
| SkylarkProviderIdentifier.forKey(JavaInfo.PROVIDER.getKey()))))) |
| .override(attr("$testsupport", LABEL).value(environment.getToolsLabel(JUNIT_TESTRUNNER))) |
| .add( |
| attr("$robolectric_implicit_classpath", LABEL_LIST) |
| .value(ImmutableList.of(environment.getToolsLabel("//tools/android:android_jar")))) |
| .override(attr("stamp", TRISTATE).value(TriState.NO)) |
| .removeAttribute("classpath_resources") |
| .removeAttribute("create_executable") |
| .removeAttribute("deploy_manifest_lines") |
| .removeAttribute("distribs") |
| .removeAttribute("launcher") |
| .removeAttribute("main_class") |
| .removeAttribute("resources") |
| .removeAttribute("use_testrunner") |
| .removeAttribute(":java_launcher") |
| .cfg( |
| new ConfigFeatureFlagTransitionFactory(AndroidFeatureFlagSetProvider.FEATURE_FLAG_ATTR)) |
| .addRequiredToolchains(CppRuleClasses.ccToolchainTypeAttribute(environment)) |
| .build(); |
| } |
| |
| @Override |
| public Metadata getMetadata() { |
| return RuleDefinition.Metadata.builder() |
| .name("android_local_test") |
| .type(RuleClassType.TEST) |
| .ancestors( |
| AndroidLocalTestBaseRule.class, |
| BaseJavaBinaryRule.class, |
| BaseRuleClasses.TestBaseRule.class) |
| .factoryClass(BazelAndroidLocalTest.class) |
| .build(); |
| } |
| } |
| |
| /*<!-- #BLAZE_RULE (NAME = android_local_test, TYPE = TEST, FAMILY = Android) --> |
| |
| <p> |
| This rule is for unit testing <code>android_library</code> rules locally |
| (as opposed to on a device). |
| It works with the Android Robolectric testing framework. |
| See the <a href="http://robolectric.org/">Android Robolectric</a> site for details about |
| writing Robolectric tests. |
| </p> |
| |
| ${IMPLICIT_OUTPUTS} |
| |
| <h4 id="android_local_test_examples">Examples</h4> |
| |
| <p> |
| To use Robolectric with <code>android_local_test</code>, add |
| <a href="https://github.com/robolectric/robolectric-bazel/tree/master/bazel">Robolectric's |
| repository</a> to your <code>WORKSPACE</code> file: |
| <pre class="code"> |
| http_archive( |
| name = "robolectric", |
| urls = ["https://github.com/robolectric/robolectric/archive/<COMMIT>.tar.gz"], |
| strip_prefix = "robolectric-<COMMIT>", |
| sha256 = "<HASH>", |
| ) |
| load("@robolectric//bazel:robolectric.bzl", "robolectric_repositories") |
| robolectric_repositories() |
| </pre> |
| |
| This pulls in the <code>maven_jar</code> rules needed for Robolectric. |
| |
| Then each <code>android_local_test</code> rule should depend on |
| <code>@robolectric//bazel:robolectric</code>. See example below. |
| |
| </p> |
| |
| <pre class="code"> |
| android_local_test( |
| name = "SampleTest", |
| srcs = [ |
| "SampleTest.java", |
| ], |
| manifest = "LibManifest.xml", |
| deps = [ |
| ":sample_test_lib", |
| "@robolectric//bazel:robolectric", |
| ], |
| ) |
| |
| android_library( |
| name = "sample_test_lib", |
| srcs = [ |
| "Lib.java", |
| ], |
| resource_files = glob(["res/**"]), |
| manifest = "AndroidManifest.xml", |
| ) |
| </pre> |
| |
| <!-- #END_BLAZE_RULE --> */ |
| |
| /* <!-- #BLAZE_RULE(android_local_test).IMPLICIT_OUTPUTS --> |
| <ul> |
| <li><code><var>name</var>.jar</code>: A Java archive of the test.</li> |
| <li><code><var>name</var>-src.jar</code>: An archive containing the sources |
| ("source jar").</li> |
| <li><code><var>name</var>_deploy.jar</code>: A Java deploy archive suitable |
| for deployment (only built if explicitly requested).</li> |
| </ul> |
| <!-- #END_BLAZE_RULE.IMPLICIT_OUTPUTS --> */ |