/*
* Copyright 2012-present Facebook, Inc.
*
* 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.facebook.buck.android;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.facebook.buck.io.MorePathsForTests;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.environment.Platform;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Files;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class AndroidPlatformTargetTest {
@Rule public TemporaryFolder tempDir = new TemporaryFolder();
@Rule public TemporaryFolder projectRoot = new TemporaryFolder();
@Test
public void testCreateFromDefaultDirectoryStructure() {
String name = "Example Inc.:Google APIs:16";
Path androidSdkDir = MorePathsForTests.rootRelativePath("home/android");
String platformDirectoryPath = "platforms/android-16";
Set<Path> additionalJarPaths = ImmutableSet.of();
AndroidDirectoryResolver androidDirectoryResolver =
new FakeAndroidDirectoryResolver(
Optional.of(androidSdkDir),
/* buildToolsDir */ Optional.of(androidSdkDir.resolve("platform-tools")),
/* androidNdkDir */ Optional.empty(),
/* ndkVersion */ Optional.empty());
AndroidPlatformTarget androidPlatformTarget =
AndroidPlatformTarget.createFromDefaultDirectoryStructure(
name,
androidDirectoryResolver,
platformDirectoryPath,
additionalJarPaths,
/* aaptOverride */ Optional.empty(),
/* aapt2Override */ Optional.empty());
assertEquals(name, androidPlatformTarget.getName());
assertEquals(
ImmutableList.of(
MorePathsForTests.rootRelativePath("home/android/platforms/android-16/android.jar")),
androidPlatformTarget.getBootclasspathEntries());
assertEquals(
MorePathsForTests.rootRelativePath("home/android/platforms/android-16/android.jar"),
androidPlatformTarget.getAndroidJar());
assertEquals(
MorePathsForTests.rootRelativePath("home/android/platforms/android-16/framework.aidl"),
androidPlatformTarget.getAndroidFrameworkIdlFile());
assertEquals(
MorePathsForTests.rootRelativePath("home/android/tools/proguard/lib/proguard.jar"),
androidPlatformTarget.getProguardJar());
assertEquals(
MorePathsForTests.rootRelativePath("home/android/tools/proguard/proguard-android.txt"),
androidPlatformTarget.getProguardConfig());
assertEquals(
MorePathsForTests.rootRelativePath(
"home/android/tools/proguard/proguard-android-optimize.txt"),
androidPlatformTarget.getOptimizedProguardConfig());
assertEquals(
androidSdkDir.resolve("platform-tools/aapt").toAbsolutePath(),
androidPlatformTarget.getAaptExecutable());
assertEquals(
androidSdkDir.resolve("platform-tools/aidl"), androidPlatformTarget.getAidlExecutable());
assertEquals(
androidSdkDir.resolve(
Platform.detect() == Platform.WINDOWS ? "platform-tools/dx.bat" : "platform-tools/dx"),
androidPlatformTarget.getDxExecutable());
}
@Test
public void testLooksForAdditionalAddonsDirectories() throws IOException {
File androidSdkDir = tempDir.newFolder();
File buildToolsDir = new File(androidSdkDir, "build-tools");
buildToolsDir.mkdir();
buildToolsDir = new File(buildToolsDir, "android-4.2.2");
buildToolsDir.mkdir();
AndroidDirectoryResolver androidDirectoryResolver =
new FakeAndroidDirectoryResolver(
Optional.of(androidSdkDir.toPath()),
Optional.of(buildToolsDir.toPath()),
/* androidNdkDir */ Optional.empty(),
/* ndkVersion */ Optional.empty());
File addOnsLibsDir1 = new File(androidSdkDir, "add-ons/addon-google_apis-google-17/libs");
addOnsLibsDir1.mkdirs();
File addOnsLibsDir2 = new File(androidSdkDir, "add-ons/addon-google_apis-google-17-2/libs");
addOnsLibsDir2.mkdirs();
Files.touch(new File(addOnsLibsDir2, "effects.jar"));
// '-11' to test that the sorting works correctly.
File addOnsLibsDir3 = new File(androidSdkDir, "add-ons/addon-google_apis-google-17-11/libs");
addOnsLibsDir3.mkdirs();
Files.touch(new File(addOnsLibsDir3, "ignored.jar"));
AndroidPlatformTarget androidPlatformTarget =
AndroidPlatformTarget.getTargetForId(
"Google Inc.:Google APIs:17",
androidDirectoryResolver,
/* aaptOverride */ Optional.empty(),
/* aapt2Override */ Optional.empty());
// Verify that addOnsLibsDir2 was picked up since addOnsLibsDir1 is empty.
assertTrue(
androidPlatformTarget
.getBootclasspathEntries()
.contains(addOnsLibsDir2.toPath().resolve("effects.jar").toAbsolutePath()));
assertFalse(
androidPlatformTarget
.getBootclasspathEntries()
.contains(addOnsLibsDir3.toPath().resolve("ignored.jar").toAbsolutePath()));
}
@Test
public void testLooksForOptionalLibraries() throws IOException {
File androidSdkDir = tempDir.newFolder();
Path pathToAndroidSdkDir = androidSdkDir.toPath();
File buildToolsDir = new File(new File(androidSdkDir, "build-tools"), "23.0.1");
buildToolsDir.mkdirs();
AndroidDirectoryResolver androidDirectoryResolver =
new FakeAndroidDirectoryResolver(
Optional.of(androidSdkDir.toPath()),
Optional.of(buildToolsDir.toPath()),
/* androidNdkDir */ Optional.empty(),
/* ndkVersion */ Optional.empty());
File optionalLibsDir = new File(androidSdkDir, "platforms/android-23/optional");
optionalLibsDir.mkdirs();
Files.touch(new File(optionalLibsDir, "httpclient.jar"));
Files.touch(new File(optionalLibsDir, "telemetry.jar"));
File addOnsLibsDir = new File(androidSdkDir, "add-ons/addon-google_apis-google-23/libs");
addOnsLibsDir.mkdirs();
Files.touch(new File(addOnsLibsDir, "effects.jar"));
Files.touch(new File(addOnsLibsDir, "maps.jar"));
Files.touch(new File(addOnsLibsDir, "usb.jar"));
String platformId = "Google Inc.:Google APIs:23";
AndroidPlatformTarget androidPlatformTarget =
AndroidPlatformTarget.getTargetForId(
platformId,
androidDirectoryResolver,
/* aaptOverride */ Optional.empty(),
/* aapt2Override */ Optional.empty());
assertEquals(platformId, androidPlatformTarget.getName());
assertEquals(
ImmutableList.of(
pathToAndroidSdkDir.resolve("platforms/android-23/android.jar"),
pathToAndroidSdkDir.resolve("platforms/android-23/optional/httpclient.jar"),
pathToAndroidSdkDir.resolve("platforms/android-23/optional/telemetry.jar"),
pathToAndroidSdkDir.resolve("add-ons/addon-google_apis-google-23/libs/effects.jar"),
pathToAndroidSdkDir.resolve("add-ons/addon-google_apis-google-23/libs/maps.jar"),
pathToAndroidSdkDir.resolve("add-ons/addon-google_apis-google-23/libs/usb.jar")),
androidPlatformTarget.getBootclasspathEntries());
assertEquals(
pathToAndroidSdkDir.resolve("platforms/android-23/android.jar"),
androidPlatformTarget.getAndroidJar());
}
@Test
public void testThrowsExceptionWhenAddOnsDirectoryIsMissing() throws IOException {
File androidSdkDir = tempDir.newFolder();
String platformId = "Google Inc.:Google APIs:17";
AndroidDirectoryResolver androidDirectoryResolver =
new FakeAndroidDirectoryResolver(
Optional.of(androidSdkDir.toPath()),
/* buildToolsDir */ Optional.empty(),
/* androidNdkDir */ Optional.empty(),
/* ndkVersion */ Optional.empty());
try {
AndroidPlatformTarget.getTargetForId(
platformId,
androidDirectoryResolver,
/* aaptOverride */ Optional.empty(),
/* aapt2Override */ Optional.empty());
fail("Should have thrown HumanReadableException");
} catch (HumanReadableException e) {
assertEquals(
String.format(
"Google APIs not found in %s.\n"
+ "Please run '%s/tools/android sdk' and select both 'SDK Platform' and "
+ "'Google APIs' under Android (API 17)",
new File(androidSdkDir, "add-ons/addon-google_apis-google-17/libs").getAbsolutePath(),
androidSdkDir.getPath()),
e.getMessage());
}
}
@Test
public void testLooksForGoogleLibsOnlyWhenGoogleApiTarget() throws IOException {
File androidSdkDir = tempDir.newFolder();
Path pathToAndroidSdkDir = androidSdkDir.toPath();
File buildToolsDir = new File(androidSdkDir, "build-tools");
buildToolsDir.mkdir();
buildToolsDir = new File(buildToolsDir, "android-4.2.2");
buildToolsDir.mkdir();
AndroidDirectoryResolver androidDirectoryResolver =
new FakeAndroidDirectoryResolver(
Optional.of(androidSdkDir.toPath()),
Optional.of(buildToolsDir.toPath()),
/* androidNdkDir */ Optional.empty(),
/* ndkVersion */ Optional.empty());
File addOnsLibsDir = new File(androidSdkDir, "add-ons/addon-google_apis-google-17/libs");
addOnsLibsDir.mkdirs();
Files.touch(new File(addOnsLibsDir, "effects.jar"));
Files.touch(new File(addOnsLibsDir, "maps.jar"));
Files.touch(new File(addOnsLibsDir, "usb.jar"));
// This one should include the Google jars
AndroidPlatformTarget androidPlatformTarget1 =
AndroidPlatformTarget.getTargetForId(
"Google Inc.:Google APIs:17",
androidDirectoryResolver,
/* aaptOverride */ Optional.empty(),
/* aapt2Override */ Optional.empty());
assertEquals(
ImmutableList.of(
pathToAndroidSdkDir.resolve("platforms/android-17/android.jar"),
pathToAndroidSdkDir.resolve("add-ons/addon-google_apis-google-17/libs/effects.jar"),
pathToAndroidSdkDir.resolve("add-ons/addon-google_apis-google-17/libs/maps.jar"),
pathToAndroidSdkDir.resolve("add-ons/addon-google_apis-google-17/libs/usb.jar")),
androidPlatformTarget1.getBootclasspathEntries());
// This one should only include android.jar
AndroidPlatformTarget androidPlatformTarget2 =
AndroidPlatformTarget.getTargetForId(
"android-17",
androidDirectoryResolver,
/* aaptOverride */ Optional.empty(),
/* aapt2Override */ Optional.empty());
assertEquals(
ImmutableList.of(pathToAndroidSdkDir.resolve("platforms/android-17/android.jar")),
androidPlatformTarget2.getBootclasspathEntries());
}
@Test
public void testPlatformTargetFindsCorrectZipAlign() throws IOException {
File androidSdkDir = tempDir.newFolder();
Path pathToAndroidSdkDir = androidSdkDir.toPath();
File buildToolsDirFromOldUpgradePath =
new File(new File(androidSdkDir, "build-tools"), "17.0.0");
buildToolsDirFromOldUpgradePath.mkdirs();
AndroidDirectoryResolver androidDirectoryResolver =
new FakeAndroidDirectoryResolver(
Optional.of(androidSdkDir.toPath()),
Optional.of(buildToolsDirFromOldUpgradePath.toPath()),
/* androidNdkDir */ Optional.empty(),
/* ndkVersion */ Optional.empty());
Files.touch(new File(buildToolsDirFromOldUpgradePath, "zipalign"));
File addOnsLibsDir = new File(androidSdkDir, "add-ons/addon-google_apis-google-17/libs");
addOnsLibsDir.mkdirs();
Files.touch(new File(addOnsLibsDir, "effects.jar"));
String platformId = "Google Inc.:Google APIs:17";
AndroidPlatformTarget androidPlatformTarget =
AndroidPlatformTarget.getTargetForId(
platformId,
androidDirectoryResolver,
/* aaptOverride */ Optional.empty(),
/* aapt2Override */ Optional.empty());
assertEquals(platformId, androidPlatformTarget.getName());
assertEquals(
pathToAndroidSdkDir.resolve("build-tools/17.0.0/zipalign"),
androidPlatformTarget.getZipalignExecutable());
File toolsDir = new File(androidSdkDir, "tools");
toolsDir.mkdirs();
Files.touch(new File(toolsDir, "zipalign"));
androidPlatformTarget =
AndroidPlatformTarget.getTargetForId(
platformId,
androidDirectoryResolver,
/* aaptOverride */ Optional.empty(),
/* aapt2Override */ Optional.empty());
assertEquals(platformId, androidPlatformTarget.getName());
assertEquals(
pathToAndroidSdkDir.resolve("tools/zipalign"),
androidPlatformTarget.getZipalignExecutable());
}
@Test
public void testPlatformTargetPattern() {
testPlatformTargetRegex("Google Inc.:Google APIs:8", true, "8");
testPlatformTargetRegex("Google Inc.:Google APIs:17", true, "17");
testPlatformTargetRegex("Google Inc.:Google APIs:MNC", true, "MNC");
testPlatformTargetRegex("android-8", true, "8");
testPlatformTargetRegex("android-17", true, "17");
testPlatformTargetRegex("android-MNC", true, "MNC");
testPlatformTargetRegex("Google Inc.:Google APIs:", false, "");
testPlatformTargetRegex("android-", false, "");
}
private void testPlatformTargetRegex(String input, boolean matches, String id) {
Matcher matcher = AndroidPlatformTarget.PLATFORM_TARGET_PATTERN.matcher(input);
assertEquals(matches, matcher.matches());
if (matches) {
assertEquals(id, matcher.group(1));
}
}
}