/* * Copyright 2014-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.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeThat; import static org.junit.Assume.assumeTrue; import com.facebook.buck.cxx.CxxDescriptionEnhancer; import com.facebook.buck.io.MorePaths; import com.facebook.buck.io.ProjectFilesystem; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.BuildTargetFactory; import com.facebook.buck.model.BuildTargets; import com.facebook.buck.testutil.integration.ProjectWorkspace; import com.facebook.buck.testutil.integration.TemporaryPaths; import com.facebook.buck.testutil.integration.TestDataHelper; import com.google.common.base.Charsets; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Optional; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @RunWith(Parameterized.class) public class NdkCxxPlatformIntegrationTest { @Parameterized.Parameters(name = "{0},{1},{2}") public static Collection<Object[]> data() { List<Object[]> data = new ArrayList<>(); for (String arch : ImmutableList.of("arm", "armv7", "arm64", "x86", "x86_64")) { data.add(new Object[] {NdkCxxPlatformCompiler.Type.GCC, NdkCxxRuntime.GNUSTL, arch}); // We don't support 64-bit clang yet. if (!arch.equals("arm64") && !arch.equals("x86_64")) { data.add(new Object[] {NdkCxxPlatformCompiler.Type.CLANG, NdkCxxRuntime.GNUSTL, arch}); data.add(new Object[] {NdkCxxPlatformCompiler.Type.CLANG, NdkCxxRuntime.LIBCXX, arch}); } } return data; } @Parameterized.Parameter public NdkCxxPlatformCompiler.Type compiler; @Parameterized.Parameter(value = 1) public NdkCxxRuntime cxxRuntime; @Parameterized.Parameter(value = 2) public String arch; @Rule public TemporaryPaths tmp = new TemporaryPaths(); private ProjectWorkspace setupWorkspace(String name) throws IOException { ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(this, name, tmp); workspace.setUp(); workspace.writeContentsToPath( String.format( "[ndk]\n" + " compiler = %s\n" + " gcc_version = 4.9\n" + " cxx_runtime = %s\n" + " cpu_abis = arm, armv7, arm64, x86, x86_64\n" + " app_platform = android-21\n", compiler, cxxRuntime), ".buckconfig"); return workspace; } private Path getNdkRoot() throws InterruptedException { ProjectFilesystem projectFilesystem = new ProjectFilesystem(Paths.get(".").toAbsolutePath()); DefaultAndroidDirectoryResolver resolver = new DefaultAndroidDirectoryResolver( projectFilesystem.getRootPath().getFileSystem(), ImmutableMap.copyOf(System.getenv()), Optional.empty(), Optional.empty()); Optional<Path> ndkDir = resolver.getNdkOrAbsent(); assertTrue(ndkDir.isPresent()); assertTrue(java.nio.file.Files.exists(ndkDir.get())); return ndkDir.get(); } @Before public void setUp() throws InterruptedException { AssumeAndroidPlatform.assumeNdkIsAvailable(); } @Test public void runtimeSupportsStl() throws InterruptedException, IOException { assumeTrue( "libcxx is unsupported with this ndk", NdkCxxPlatforms.isSupportedConfiguration(getNdkRoot(), cxxRuntime)); ProjectWorkspace workspace = setupWorkspace("runtime_stl"); workspace.runBuckCommand("build", String.format("//:main#android-%s", arch)).assertSuccess(); } @Test public void changedPlatformTarget() throws InterruptedException, IOException { assumeTrue( "libcxx is unsupported with this ndk", NdkCxxPlatforms.isSupportedConfiguration(getNdkRoot(), cxxRuntime)); // 64-bit only works with platform 21, so we can't change the platform to anything else. assumeThat( "skip this test for 64-bit, for now", arch, not(anyOf(equalTo("arm64"), equalTo("x86_64")))); ProjectWorkspace workspace = setupWorkspace("ndk_app_platform"); BuildTarget target = BuildTargetFactory.newInstance(String.format("//:main#android-%s", arch)); BuildTarget linkTarget = CxxDescriptionEnhancer.createCxxLinkTarget(target, Optional.empty()); workspace.runBuckCommand("build", target.toString()).assertSuccess(); workspace.getBuildLog().assertTargetBuiltLocally(linkTarget.toString()); // Change the app platform and verify that our rulekey has changed. workspace.writeContentsToPath("[ndk]\n app_platform = android-12", ".buckconfig"); workspace.runBuckCommand("build", target.toString()).assertSuccess(); workspace.getBuildLog().assertTargetBuiltLocally(linkTarget.toString()); } @Test public void testWorkingDirectoryAndNdkHeaderPathsAreSanitized() throws InterruptedException, IOException { ProjectWorkspace workspace = setupWorkspace("ndk_debug_paths"); workspace.writeContentsToPath( "[ndk]\n" + " cpu_abis = arm, armv7, arm64, x86, x86_64\n" + " gcc_version = 4.9\n" + " app_platform = android-21\n", ".buckconfig"); ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath()); BuildTarget target = BuildTargetFactory.newInstance(String.format("//:lib#android-%s,static", arch)); workspace.runBuckBuild(target.getFullyQualifiedName()).assertSuccess(); Path lib = workspace.getPath( BuildTargets.getGenPath(filesystem, target, "%s/lib" + target.getShortName() + ".a")); String contents = MorePaths.asByteSource(lib).asCharSource(Charsets.ISO_8859_1).read(); // Verify that the working directory is sanitized. assertFalse(contents.contains(tmp.getRoot().toString())); // Verify that we don't have any references to the build toolchain in the debug info. for (NdkCxxPlatforms.Host host : NdkCxxPlatforms.Host.values()) { assertFalse(contents.contains(host.toString())); } // Verify that the NDK path is sanitized. assertFalse(contents.contains(getNdkRoot().toString())); } }