/* * 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.jvm.java; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeThat; import com.facebook.buck.jvm.java.testutil.AbiCompilationModeTest; import com.facebook.buck.testutil.integration.ProjectWorkspace; import com.facebook.buck.testutil.integration.TemporaryPaths; import com.facebook.buck.testutil.integration.TestDataHelper; import com.facebook.buck.testutil.integration.ZipInspector; import com.facebook.buck.util.ProcessExecutor; import com.facebook.buck.util.environment.Platform; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.jar.JarFile; import org.junit.Before; import org.junit.Rule; import org.junit.Test; public class JavaBinaryIntegrationTest extends AbiCompilationModeTest { @Rule public TemporaryPaths tmp = new TemporaryPaths(); private ProjectWorkspace workspace; @Before public void checkPlatform() { assumeThat(Platform.detect(), not(Platform.WINDOWS)); } @Test public void fatJarLoadingNativeLibraries() throws IOException { setUpProjectWorkspaceForScenario("fat_jar"); workspace.runBuckCommand("run", "//:bin-fat").assertSuccess(); } @Test public void fatJarOutputIsRecorded() throws IOException, InterruptedException { setUpProjectWorkspaceForScenario("fat_jar"); workspace.enableDirCache(); workspace.runBuckCommand("build", "//:bin-fat").assertSuccess(); workspace.runBuckCommand("clean"); Path path = workspace.buildAndReturnOutput("//:bin-fat"); workspace.getBuildLog().assertTargetWasFetchedFromCache("//:bin-fat"); assertTrue(workspace.asCell().getFilesystem().exists(path)); } @Test public void fatJarWithOutput() throws IOException, InterruptedException { setUpProjectWorkspaceForScenario("fat_jar"); Path jar = workspace.buildAndReturnOutput("//:bin-output"); ProcessExecutor.Result result = workspace.runJar(jar); assertEquals("output", result.getStdout().get().trim()); assertEquals("error", result.getStderr().get().trim()); } @Test public void disableCachingForBinaries() throws IOException { setUpProjectWorkspaceForScenario("java_binary_with_blacklist"); workspace.enableDirCache(); workspace .runBuckBuild("-c", "java.cache_binaries=false", "//:bin-no-blacklist") .assertSuccess(); workspace.runBuckCommand("clean").assertSuccess(); workspace .runBuckBuild("-c", "java.cache_binaries=false", "//:bin-no-blacklist") .assertSuccess(); workspace.getBuildLog().assertTargetBuiltLocally("//:bin-no-blacklist"); } @Test public void fatJarWithExitCode() throws IOException { setUpProjectWorkspaceForScenario("fat_jar"); workspace.runBuckCommand("run", "//:bin-exit-code").assertSpecialExitCode("error", 5); } @Test public void fatJarWithVmArguments() throws IOException, InterruptedException { setUpProjectWorkspaceForScenario("fat_jar"); ImmutableList<String> args = ImmutableList.of("-ea", "-Dfoo.bar.baz=1234", "-Xms64m"); String expected = Joiner.on("\n").join(args); Path jar = workspace.buildAndReturnOutput("//:bin-jvm-args"); ProcessExecutor.Result result = workspace.runJar(jar, args); assertEquals(expected, result.getStdout().get().trim()); } @Test public void fatJarWithAlternateJavaBin() throws IOException, InterruptedException { setUpProjectWorkspaceForScenario("fat_jar"); Path jar = workspace.buildAndReturnOutput("//:bin-alternate-java"); String javaHomeArg = "-Dbuck.fatjar.java.home=" + tmp.getRoot().toString(); ProcessExecutor.Result result = workspace.runJar(jar, ImmutableList.of(javaHomeArg)); assertEquals("Running java wrapper\nRunning inner jar", result.getStdout().get().trim()); } @Test public void jarWithMetaInfo() throws IOException, InterruptedException { setUpProjectWorkspaceForScenario("java_binary_with_meta_inf"); Path jar = workspace.buildAndReturnOutput("//:bin-meta-inf"); try (JarFile jarFile = new JarFile(jar.toFile())) { assertNotNull(jarFile.getEntry("META-INF/test.txt")); } } @Test public void fatJarWithBlacklist() throws IOException { setUpProjectWorkspaceForScenario("java_binary_with_blacklist"); Path binaryJarWithBlacklist = workspace.buildAndReturnOutput("//:bin-blacklist"); Path binaryJarWithoutBlacklist = workspace.buildAndReturnOutput("//:bin-no-blacklist"); ImmutableSet<String> commonEntries = ImmutableSet.of( "META-INF/", "META-INF/MANIFEST.MF", "com/", "com/example/", "com/example/B.class"); ImmutableSet<String> blacklistedEntries = ImmutableSet.of( "com/example/A.class", "com/example/A$C.class", "com/example/Alligator.class"); assertEquals( "com.example.Alligator, com.example.A and any inner classes should be removed.", commonEntries, new ZipInspector(binaryJarWithBlacklist).getZipFileEntries()); assertEquals( ImmutableSet.builder().addAll(commonEntries).addAll(blacklistedEntries).build(), new ZipInspector(binaryJarWithoutBlacklist).getZipFileEntries()); } @Test public void testJarWithCorruptInput() throws IOException { setUpProjectWorkspaceForScenario("corruption"); workspace.runBuckBuild("//:simple-lib").assertSuccess(); String libJar = workspace .runBuckCommand("targets", "--show_output", "//:simple-lib") .assertSuccess() .getStdout() .split(" ")[1] .trim(); // Now corrupt the output jar. Path jarPath = workspace.getPath(libJar); byte[] bytes = Files.readAllBytes(jarPath); for (int backOffset = 7; backOffset <= 10; backOffset++) { bytes[bytes.length - backOffset] = 0x77; } Files.write(jarPath, bytes); ProjectWorkspace.ProcessResult result = workspace.runBuckBuild("//:wrapper_01").assertFailure(); // Should show the rule that failed. assertThat(result.getStderr(), containsString("//:simple-lib")); // Should show the jar we were operating on. assertThat(result.getStderr(), containsString(libJar)); // Should show the original exception. assertThat(result.getStderr(), containsString("ZipError")); } private ProjectWorkspace setUpProjectWorkspaceForScenario(String scenario) throws IOException { workspace = TestDataHelper.createProjectWorkspaceForScenario(this, scenario, tmp); workspace.setUp(); setWorkspaceCompilationMode(workspace); return workspace; } }