aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Adam Michael <ajmichael@google.com>2016-10-27 17:01:40 +0000
committerGravatar John Cater <jcater@google.com>2016-10-27 17:12:03 +0000
commitf2c46a0262e17c3d6f6504a0bc20fcb5ca8a4d49 (patch)
tree178420a741018c6442fbf3d42c2843a4bed316f1 /src
parent3ab8f9d343bdf63a46c04807c44a25e341f09f98 (diff)
*** Reason for rollback *** Rollforward with fixes for android_integration_test.sh *** Original change description *** Automated [] rollback of commit 2fcf0e4cfb97af7cc8b8a090c5144c87b759bc13. *** Reason for rollback *** Breaks android_integration_test, see https://github.com/bazelbuild/bazel/issues/1927 *** Original change description *** Generate aar_import and java_import rules for local maven repositories in <sdk>/extras for sdk in android_sdk_repository. Addresses https://github.com/bazelbuild/bazel/issues/1745. -- MOS_MIGRATED_REVID=137407118
Diffstat (limited to 'src')
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java24
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/android/SdkMavenRepository.java282
-rw-r--r--src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_sdk_repository_template.txt3
-rw-r--r--src/test/java/com/google/devtools/build/lib/BUILD3
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java5
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisMock.java5
-rw-r--r--src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryTest.java67
-rw-r--r--src/test/java/com/google/devtools/build/lib/bazel/rules/android/SdkMavenRepositoryTest.java139
8 files changed, 527 insertions, 1 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java
index 5852a19012..b916bdddf4 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryFunction.java
@@ -13,6 +13,9 @@
// limitations under the License.
package com.google.devtools.build.lib.bazel.rules.android;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.RuleDefinition;
import com.google.devtools.build.lib.packages.AttributeMap;
@@ -35,6 +38,7 @@ import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import java.io.IOException;
import java.util.Properties;
+import javax.annotation.Nullable;
/**
* Implementation of the {@code android_sdk_repository} rule.
@@ -90,6 +94,26 @@ public class AndroidSdkRepositoryFunction extends RepositoryFunction {
.replaceAll("%build_tools_directory%", buildToolsDirectory)
.replaceAll("%api_level%", apiLevel.toString());
+ // All local maven repositories that are shipped in the Android SDK.
+ // TODO(ajmichael): Create SkyKeys so that if the SDK changes, this function will get rerun.
+ Iterable<Path> localMavenRepositories = ImmutableList.of(
+ outputDirectory.getRelative("extras/android/m2repository"),
+ outputDirectory.getRelative("extras/google/m2repository"));
+ try {
+ SdkMavenRepository sdkExtrasRepository =
+ SdkMavenRepository.create(Iterables.filter(localMavenRepositories, new Predicate<Path>() {
+ @Override
+ public boolean apply(@Nullable Path path) {
+ return path.isDirectory();
+ }
+ }));
+ sdkExtrasRepository.writeBuildFiles(outputDirectory);
+ buildFile = buildFile.replaceAll(
+ "%exported_files%", sdkExtrasRepository.getExportsFiles(outputDirectory));
+ } catch (IOException e) {
+ throw new RepositoryFunctionException(e, Transience.TRANSIENT);
+ }
+
writeBuildFile(outputDirectory, buildFile);
return RepositoryDirectoryValue.create(outputDirectory);
}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/SdkMavenRepository.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/SdkMavenRepository.java
new file mode 100644
index 0000000000..136da18742
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/SdkMavenRepository.java
@@ -0,0 +1,282 @@
+// Copyright 2016 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 com.google.auto.value.AutoValue;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Ordering;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
+import com.google.devtools.build.lib.vfs.Path;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collection;
+import javax.annotation.Nullable;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+/**
+ * A collection of .pom contents that reference versioned archive files with dependencies.
+ */
+final class SdkMavenRepository {
+ private enum PackagingType {
+ AAR {
+ @Override
+ ImmutableList<String> createRule(
+ String name, String archiveLabel, ImmutableList<String> dependencyLabels) {
+ ImmutableList.Builder<String> ruleLines = new ImmutableList.Builder<>();
+ ruleLines.add("aar_import(");
+ ruleLines.add(" name = '" + name + "',");
+ ruleLines.add(" aar = '" + archiveLabel + "',");
+ ruleLines.add(" exports = [");
+ for (String dependencyLabel : dependencyLabels) {
+ ruleLines.add(" '" + dependencyLabel + "',");
+ }
+ ruleLines.add(" ],");
+ ruleLines.add(")");
+ ruleLines.add("");
+ return ruleLines.build();
+ }
+ },
+ JAR {
+ @Override
+ ImmutableList<String> createRule(
+ String name, String archiveLabel, ImmutableList<String> dependencyLabels) {
+ ImmutableList.Builder<String> ruleLines = new ImmutableList.Builder<>();
+ ruleLines.add("java_import(");
+ ruleLines.add(" name = '" + name + "',");
+ ruleLines.add(" jars = ['" + archiveLabel + "'],");
+ ruleLines.add(" exports = [");
+ for (String dependencyLabel : dependencyLabels) {
+ ruleLines.add(" '" + dependencyLabel + "',");
+ }
+ ruleLines.add(" ],");
+ ruleLines.add(")");
+ ruleLines.add("");
+ return ruleLines.build();
+ }
+ },
+ UNKNOWN {
+ @Override
+ ImmutableList<String> createRule(String name, String archiveLabel,
+ ImmutableList<String> dependencyLabels) {
+ ImmutableList.Builder<String> ruleLines = new ImmutableList.Builder<>();
+ ruleLines.add("genrule(");
+ ruleLines.add(" name = '" + name + "',");
+ ruleLines.add(" outs = ['ignored_" + name + "'],");
+ ruleLines.add(" cmd = 'echo Bazel does not recognize the Maven packaging type for: \""
+ + archiveLabel + "\"; exit 1',");
+ ruleLines.add(")");
+ ruleLines.add("");
+ return ruleLines.build();
+ }
+ };
+
+ static PackagingType getPackagingType(String name) {
+ for (PackagingType packagingType : PackagingType.values()) {
+ if (packagingType.name().equalsIgnoreCase(name)) {
+ return packagingType;
+ }
+ }
+ return UNKNOWN;
+ }
+
+ abstract ImmutableList<String> createRule(
+ String name, String archiveLabel, ImmutableList<String> dependencyLabels);
+ }
+
+ private final ImmutableSortedSet<Pom> poms;
+ private final ImmutableSet<MavenCoordinate> allKnownCoordinates;
+
+ private SdkMavenRepository(ImmutableSortedSet<Pom> poms) {
+ this.poms = poms;
+ ImmutableSet.Builder<MavenCoordinate> coordinates = new ImmutableSet.Builder<>();
+ for (Pom pom : poms) {
+ if (!PackagingType.getPackagingType(pom.packaging()).equals(PackagingType.UNKNOWN)) {
+ coordinates.add(pom.mavenCoordinate());
+ }
+ }
+ allKnownCoordinates = coordinates.build();
+ }
+
+ /**
+ * Parses a set of maven repository directory trees looking for and parsing .pom files.
+ */
+ static SdkMavenRepository create(Iterable<Path> mavenRepositories) throws IOException {
+ Collection<Path> pomPaths = new ArrayList<>();
+ for (Path mavenRepository : mavenRepositories) {
+ pomPaths.addAll(FileSystemUtils.traverseTree(mavenRepository, new Predicate<Path>() {
+ @Override
+ public boolean apply(@Nullable Path path) {
+ return path.toString().endsWith(".pom");
+ }
+ }));
+ }
+
+ ImmutableSortedSet.Builder<Pom> poms =
+ new ImmutableSortedSet.Builder<>(Ordering.usingToString());
+ for (Path pomPath : pomPaths) {
+ try {
+ Pom pom = Pom.parse(pomPath);
+ if (pom != null) {
+ poms.add(pom);
+ }
+ } catch (ParserConfigurationException | SAXException e) {
+ throw new IOException(e);
+ }
+ }
+ return new SdkMavenRepository(poms.build());
+ }
+
+ /**
+ * Creates BUILD files at {@code @<android sdk>/<group id>/BUILD} containing aar_import and
+ * java_import rules with dependencies as {@code exports}. The targets are named
+ * {@code @<android sdk>//<group id>:<artifact id>-<version id>}.
+ */
+ void writeBuildFiles(Path outputDirectory) throws IOException {
+ for (Pom pom : poms) {
+ Path buildFilePath = outputDirectory.getRelative(pom.mavenCoordinate().groupId() + "/BUILD");
+
+ if (!buildFilePath.getParentDirectory().exists()) {
+ buildFilePath.getParentDirectory().createDirectory();
+ }
+
+ if (!buildFilePath.exists()) {
+ FileSystemUtils.writeContentAsLatin1(
+ buildFilePath, "package(default_visibility = [\"//visibility:public\"])\n\n");
+ }
+
+ ImmutableList.Builder<String> dependencyLabels = new ImmutableList.Builder<>();
+ for (MavenCoordinate dependencyCoordinate : pom.dependencyCoordinates()) {
+ // Filter out dependencies that are not present in the Maven repository or have unknown
+ // packaging types.
+ if (allKnownCoordinates.contains(dependencyCoordinate)) {
+ dependencyLabels.add(dependencyCoordinate.targetLabel());
+ }
+ }
+
+ ImmutableList<String> ruleLines = PackagingType.getPackagingType(pom.packaging())
+ .createRule(
+ pom.mavenCoordinate().targetName(),
+ pom.archiveLabel(outputDirectory),
+ dependencyLabels.build());
+ FileSystemUtils.appendLinesAs(buildFilePath, StandardCharsets.ISO_8859_1, ruleLines);
+ }
+ }
+
+ /**
+ * Creates the contents of the exports_files rule list containing all of the archives specified by
+ * the pom files in the Maven repositories.
+ */
+ String getExportsFiles(Path outputDirectory) {
+ StringBuilder exportedFiles = new StringBuilder();
+ for (Pom pom : poms) {
+ exportedFiles.append(String.format(
+ " '%s',\n", pom.archivePath().relativeTo(outputDirectory).getPathString()));
+ }
+ return exportedFiles.toString();
+ }
+
+ /**
+ * The relevant contents of a .pom file needed to populate BUILD files for aars and jars in the
+ * Android SDK extras maven repositories.
+ */
+ @AutoValue
+ abstract static class Pom {
+ private static final String DEFAULT_PACKAGING = "jar";
+
+ static Pom parse(Path path) throws IOException, ParserConfigurationException, SAXException {
+ Document pomDocument =
+ DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(path.getInputStream());
+ Node packagingNode = pomDocument.getElementsByTagName("packaging").item(0);
+ String packaging = packagingNode == null ? DEFAULT_PACKAGING : packagingNode.getTextContent();
+ MavenCoordinate coordinate = MavenCoordinate.create(
+ pomDocument.getElementsByTagName("groupId").item(0).getTextContent(),
+ pomDocument.getElementsByTagName("artifactId").item(0).getTextContent(),
+ pomDocument.getElementsByTagName("version").item(0).getTextContent());
+
+ ImmutableSortedSet.Builder<MavenCoordinate> dependencyCoordinates =
+ new ImmutableSortedSet.Builder<>(Ordering.usingToString());
+ NodeList dependencies = pomDocument.getElementsByTagName("dependency");
+ for (int i = 0; i < dependencies.getLength(); i++) {
+ if (dependencies.item(i) instanceof Element) {
+ Element dependency = (Element) dependencies.item(i);
+ dependencyCoordinates.add(MavenCoordinate.create(
+ dependency.getElementsByTagName("groupId").item(0).getTextContent(),
+ dependency.getElementsByTagName("artifactId").item(0).getTextContent(),
+ dependency.getElementsByTagName("version").item(0).getTextContent()));
+ }
+ }
+
+ return new AutoValue_SdkMavenRepository_Pom(
+ path, packaging, coordinate, dependencyCoordinates.build());
+ }
+
+ abstract Path path();
+
+ abstract String packaging();
+
+ abstract MavenCoordinate mavenCoordinate();
+
+ abstract ImmutableSortedSet<MavenCoordinate> dependencyCoordinates();
+
+ String name() {
+ String pomFilename = path().getBaseName();
+ return pomFilename.substring(0, pomFilename.lastIndexOf(".pom"));
+ }
+
+ Path archivePath() {
+ return path().getParentDirectory().getRelative(name() + "." + packaging());
+ }
+
+ /** The label for the .aar or .jar file in the repository. */
+ String archiveLabel(Path outputDirectory) {
+ return "//:" + archivePath().relativeTo(outputDirectory);
+ }
+ }
+
+ /**
+ * A 3-tuple of group id, artifact id and version used to identify Maven targets.
+ */
+ @AutoValue
+ abstract static class MavenCoordinate {
+ static MavenCoordinate create(String groupId, String artifactId, String version) {
+ return new AutoValue_SdkMavenRepository_MavenCoordinate(groupId, artifactId, version);
+ }
+
+ abstract String groupId();
+
+ abstract String artifactId();
+
+ abstract String version();
+
+ /** The target name for the java_import or aar_import for the Maven coordinate. */
+ String targetName() {
+ return artifactId() + "-" + version();
+ }
+
+ /** The target label for the java_import or aar_import for the Maven coordinate. */
+ String targetLabel() {
+ return "//" + groupId() + ":" + targetName();
+ }
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_sdk_repository_template.txt b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_sdk_repository_template.txt
index e82b5e4c16..2630685589 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_sdk_repository_template.txt
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/android/android_sdk_repository_template.txt
@@ -8,3 +8,6 @@ create_android_sdk_rules(
build_tools_directory = "%build_tools_directory%",
api_level = %api_level%,
)
+
+exports_files([
+%exported_files%])
diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD
index 0556e41c5a..f7ae7d599a 100644
--- a/src/test/java/com/google/devtools/build/lib/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/BUILD
@@ -959,6 +959,7 @@ java_test(
":analysis_testutil",
":foundations_testutil",
":test_runner",
+ ":testutil",
"//src/main/java/com/google/devtools/build/lib:android-rules",
"//src/main/java/com/google/devtools/build/lib:bazel-main",
"//src/main/java/com/google/devtools/build/lib:bazel-rules",
@@ -966,9 +967,11 @@ java_test(
"//src/main/java/com/google/devtools/build/lib:events",
"//src/main/java/com/google/devtools/build/lib:java-compilation",
"//src/main/java/com/google/devtools/build/lib:packages-internal",
+ "//src/main/java/com/google/devtools/build/lib:syntax",
"//src/main/java/com/google/devtools/build/lib:util",
"//src/main/java/com/google/devtools/build/lib:vfs",
"//src/main/java/com/google/devtools/build/lib/actions",
+ "//src/main/java/com/google/devtools/build/lib/cmdline",
"//src/main/protobuf:crosstool_config_java_proto",
"//src/test/java/com/google/devtools/build/lib:actions_testutil",
"//third_party:guava",
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java b/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java
index d89d4c8caf..1189d99f31 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/mock/BazelAnalysisMock.java
@@ -111,6 +111,11 @@ public final class BazelAnalysisMock extends AnalysisMock {
config.create(
"/bazel_tools_workspace/tools/android/BUILD",
androidBuildContents.toArray(new String[androidBuildContents.size()]));
+ config.create(
+ "/bazel_tools_workspace/tools/android/android_sdk_repository_template.bzl",
+ "def create_android_sdk_rules("
+ + "name, build_tools_version, build_tools_directory, api_level):",
+ " pass");
config.create(
"/bazel_tools_workspace/tools/genrule/BUILD", "exports_files(['genrule-setup.sh'])");
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisMock.java b/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisMock.java
index d01db4f360..c1c8a55fbb 100644
--- a/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisMock.java
+++ b/src/test/java/com/google/devtools/build/lib/analysis/util/AnalysisMock.java
@@ -18,6 +18,8 @@ import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.ConfigurationCollectionFactory;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.config.ConfigurationFactory;
+import com.google.devtools.build.lib.bazel.rules.android.AndroidSdkRepositoryFunction;
+import com.google.devtools.build.lib.bazel.rules.android.AndroidSdkRepositoryRule;
import com.google.devtools.build.lib.flags.InvocationPolicyEnforcer;
import com.google.devtools.build.lib.packages.PackageFactory;
import com.google.devtools.build.lib.packages.util.LoadingMock;
@@ -110,7 +112,8 @@ public abstract class AnalysisMock extends LoadingMock {
// Some tests require the local_repository rule so we need the appropriate SkyFunctions.
RepositoryFunction localRepositoryFunction = new LocalRepositoryFunction();
ImmutableMap<String, RepositoryFunction> repositoryHandlers = ImmutableMap.of(
- LocalRepositoryRule.NAME, localRepositoryFunction);
+ LocalRepositoryRule.NAME, localRepositoryFunction,
+ AndroidSdkRepositoryRule.NAME, new AndroidSdkRepositoryFunction());
return ImmutableMap.of(
SkyFunctions.REPOSITORY_DIRECTORY,
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryTest.java b/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryTest.java
new file mode 100644
index 0000000000..a970d41125
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/bazel/rules/android/AndroidSdkRepositoryTest.java
@@ -0,0 +1,67 @@
+// Copyright 2016 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.common.truth.Truth.assertThat;
+
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link AndroidNdkRepositoryFunction}. */
+@RunWith(JUnit4.class)
+public class AndroidSdkRepositoryTest extends BuildViewTestCase {
+
+ @Before
+ public void setup() throws Exception {
+ scratch.setWorkingDir("/sdk");
+ scratch.file("extras/google/m2repository/com/google/android/foo/1.0.0/foo.pom",
+ "<project>",
+ " <groupId>com.google.android</groupId>",
+ " <artifactId>foo</artifactId>",
+ " <version>1.0.0</version>",
+ " <packaging>aar</packaging>",
+ "</project>");
+
+ scratch.setWorkingDir("/workspace");
+ FileSystemUtils.appendIsoLatin1(scratch.resolve("WORKSPACE"),
+ "android_sdk_repository(",
+ " name = 'mysdk',",
+ " path = '/sdk',",
+ " build_tools_version = '24.0.0',",
+ " api_level = 24,",
+ ")");
+ }
+
+ @Test
+ public void testGeneratedAarImport() throws Exception {
+ invalidatePackages();
+ ConfiguredTarget aarImportTarget = getConfiguredTarget("@mysdk//com.google.android:foo-1.0.0");
+ assertThat(aarImportTarget.getTarget().getAssociatedRule().getRuleClass())
+ .isEqualTo("aar_import");
+ }
+
+ @Test
+ public void testExportsFiles() throws Exception {
+ invalidatePackages();
+ ConfiguredTarget aarTarget = getConfiguredTarget(
+ "@mysdk//:extras/google/m2repository/com/google/android/foo/1.0.0/foo.aar");
+ assertThat(aarTarget).isNotNull();
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/rules/android/SdkMavenRepositoryTest.java b/src/test/java/com/google/devtools/build/lib/bazel/rules/android/SdkMavenRepositoryTest.java
new file mode 100644
index 0000000000..02cf802a6a
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/bazel/rules/android/SdkMavenRepositoryTest.java
@@ -0,0 +1,139 @@
+// Copyright 2016 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.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.packages.AttributeMap;
+import com.google.devtools.build.lib.packages.BuildType;
+import com.google.devtools.build.lib.packages.RawAttributeMapper;
+import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.syntax.Type;
+import com.google.devtools.build.lib.vfs.Path;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link SdkMavenRepository}. */
+@RunWith(JUnit4.class)
+public class SdkMavenRepositoryTest extends BuildViewTestCase {
+ Path workspaceDir;
+ Path repoPath;
+ SdkMavenRepository sdkMavenRepository;
+
+ @Before
+ public void setup() throws Exception {
+ repoPath = scratch.dir("repo");
+ workspaceDir = scratch.dir("");
+
+ scratch.file("repo/com/google/android/foo/1.0.0/foo.pom",
+ "<project>",
+ " <groupId>com.google.android</groupId>",
+ " <artifactId>foo</artifactId>",
+ " <version>1.0.0</version>",
+ "</project>");
+ scratch.file("repo/com/google/android/bar/1.0.0/bar.pom",
+ "<project>",
+ " <groupId>com.google.android</groupId>",
+ " <artifactId>bar</artifactId>",
+ " <version>1.0.0</version>",
+ " <packaging>aar</packaging>",
+ " <dependencies>",
+ " <dependency>",
+ " <groupId>com.google.android</groupId>",
+ " <artifactId>foo</artifactId>",
+ " <version>1.0.0</version>",
+ " </dependency>",
+ " <dependency>",
+ " <groupId>com.google.android</groupId>",
+ " <artifactId>baz</artifactId>",
+ " <version>1.0.0</version>",
+ " </dependency>",
+ " </dependencies>",
+ "</project>");
+ scratch.file("repo/com/google/android/baz/1.0.0/baz.pom",
+ "<project>",
+ " <groupId>com.google.android</groupId>",
+ " <artifactId>baz</artifactId>",
+ " <version>1.0.0</version>",
+ " <packaging>par</packaging>",
+ "</project>");
+ sdkMavenRepository = SdkMavenRepository.create(ImmutableList.of(repoPath));
+ scratch.file("BUILD",
+ "exports_files([",
+ sdkMavenRepository.getExportsFiles(workspaceDir),
+ "])");
+ }
+
+ @Test
+ public void testExportsFiles() throws Exception {
+ assertThat(sdkMavenRepository.getExportsFiles(workspaceDir)).isEqualTo(
+ " 'repo/com/google/android/bar/1.0.0/bar.aar',\n"
+ + " 'repo/com/google/android/baz/1.0.0/baz.par',\n"
+ + " 'repo/com/google/android/foo/1.0.0/foo.jar',\n"
+ );
+ }
+
+ @Test
+ public void testBuildFilesWritten() throws Exception {
+ sdkMavenRepository.writeBuildFiles(workspaceDir);
+
+ Path groupIdPath = scratch.resolve("com.google.android");
+ assertThat(workspaceDir.getDirectoryEntries()).containsAllOf(repoPath, groupIdPath);
+
+ Path buildFilePath = groupIdPath.getRelative("BUILD");
+ assertThat(groupIdPath.getDirectoryEntries()).containsExactly(buildFilePath);
+ }
+
+ @Test
+ public void testGeneratedAarImport() throws Exception {
+ sdkMavenRepository.writeBuildFiles(workspaceDir);
+ Rule aarImport =
+ getConfiguredTarget("//com.google.android:bar-1.0.0").getTarget().getAssociatedRule();
+ assertThat(aarImport.getRuleClass()).isEqualTo("aar_import");
+ AttributeMap attributes = RawAttributeMapper.of(aarImport);
+ assertThat(attributes.get("aar", BuildType.LABEL))
+ .isEqualTo(Label.parseAbsoluteUnchecked("//:repo/com/google/android/bar/1.0.0/bar.aar"));
+ assertThat(attributes.get("exports", BuildType.LABEL_LIST))
+ .containsExactly(Label.parseAbsoluteUnchecked("//com.google.android:foo-1.0.0"));
+ }
+
+ @Test
+ public void testGeneratedJavaImport() throws Exception {
+ sdkMavenRepository.writeBuildFiles(workspaceDir);
+ Rule javaImport =
+ getConfiguredTarget("//com.google.android:foo-1.0.0").getTarget().getAssociatedRule();
+ assertThat(javaImport.getRuleClass()).isEqualTo("java_import");
+ AttributeMap attributes = RawAttributeMapper.of(javaImport);
+ assertThat(attributes.get("jars", BuildType.LABEL_LIST)).containsExactly(
+ Label.parseAbsoluteUnchecked("//:repo/com/google/android/foo/1.0.0/foo.jar"));
+ assertThat(attributes.get("exports", BuildType.LABEL_LIST)).isEmpty();
+ }
+
+ @Test
+ public void testGeneratedRuleForInvalidPackaging() throws Exception {
+ sdkMavenRepository.writeBuildFiles(workspaceDir);
+ Rule invalidPackagingGenrule =
+ getConfiguredTarget("//com.google.android:baz-1.0.0").getTarget().getAssociatedRule();
+ assertThat(invalidPackagingGenrule.getRuleClass()).isEqualTo("genrule");
+ assertThat(RawAttributeMapper.of(invalidPackagingGenrule).get("cmd", Type.STRING))
+ .isEqualTo("echo Bazel does not recognize the Maven packaging type for: "
+ + "\"//:repo/com/google/android/baz/1.0.0/baz.par\"; exit 1");
+ }
+}