| /* |
| * Copyright 2013-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.assertTrue; |
| |
| import com.facebook.buck.android.DxStep.Option; |
| import com.facebook.buck.cli.VerbosityParser; |
| import com.facebook.buck.step.ExecutionContext; |
| import com.facebook.buck.step.Step; |
| import com.facebook.buck.step.TestExecutionContext; |
| import com.facebook.buck.testutil.MoreAsserts; |
| import com.facebook.buck.testutil.TestConsole; |
| import com.facebook.buck.util.AndroidPlatformTarget; |
| import com.facebook.buck.util.Verbosity; |
| import com.google.common.base.Function; |
| import com.google.common.base.Joiner; |
| import com.google.common.base.Optional; |
| import com.google.common.base.Supplier; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.common.collect.Iterables; |
| |
| import org.easymock.EasyMock; |
| import org.easymock.EasyMockSupport; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| import java.io.File; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.EnumSet; |
| |
| public class DxStepTest extends EasyMockSupport { |
| |
| private static final String EXPECTED_DX_PREFIX = |
| "/usr/bin/dx" + |
| " --dex"; |
| |
| private static Path SAMPLE_OUTPUT_PATH = Paths.get("buck-out/gen/classes.dex"); |
| |
| private static ImmutableSet<Path> SAMPLE_FILES_TO_DEX = ImmutableSet.of( |
| Paths.get("buck-out/gen/foo.dex.jar"), |
| Paths.get("buck-out/gen/bar.dex.jar")); |
| |
| private Optional<AndroidPlatformTarget> androidPlatformTargetOptional; |
| |
| @Before |
| public void setUp() { |
| AndroidPlatformTarget androidPlatformTarget = createMock(AndroidPlatformTarget.class); |
| EasyMock.expect(androidPlatformTarget.getDxExecutable()).andReturn(new File("/usr/bin/dx")); |
| androidPlatformTargetOptional = Optional.of(androidPlatformTarget); |
| replayAll(); |
| } |
| |
| @Test |
| public void testDxCommandNoOptimizeNoJumbo() { |
| // Context with --verbose 2. |
| ExecutionContext context = createExecutionContext(2); |
| Function<Path, Path> pathAbsolutifier = context.getProjectFilesystem().getAbsolutifier(); |
| |
| DxStep dx = new DxStep(SAMPLE_OUTPUT_PATH.toString(), |
| SAMPLE_FILES_TO_DEX, |
| EnumSet.of(Option.NO_OPTIMIZE)); |
| |
| String expected = String.format("%s --no-optimize --output %s %s", |
| EXPECTED_DX_PREFIX, |
| SAMPLE_OUTPUT_PATH, |
| Joiner.on(' ').join(Iterables.transform(SAMPLE_FILES_TO_DEX, pathAbsolutifier))); |
| MoreAsserts.assertShellCommands( |
| "--no-optimize should be present, but --force-jumbo should not.", |
| ImmutableList.of(expected), |
| ImmutableList.<Step>of(dx), |
| context); |
| verifyAll(); |
| } |
| |
| @Test |
| public void testDxCommandOptimizeNoJumbo() { |
| // Context with --verbose 2. |
| ExecutionContext context = createExecutionContext(2); |
| Function<Path, Path> pathAbsolutifier = context.getProjectFilesystem().getAbsolutifier(); |
| |
| DxStep dx = new DxStep(SAMPLE_OUTPUT_PATH.toString(), SAMPLE_FILES_TO_DEX); |
| |
| String expected = String.format("%s --output %s %s", |
| EXPECTED_DX_PREFIX, |
| SAMPLE_OUTPUT_PATH, |
| Joiner.on(' ').join(Iterables.transform(SAMPLE_FILES_TO_DEX, pathAbsolutifier))); |
| MoreAsserts.assertShellCommands( |
| "Neither --no-optimize nor --force-jumbo should be present.", |
| ImmutableList.of(expected), |
| ImmutableList.<Step>of(dx), |
| context); |
| verifyAll(); |
| } |
| |
| @Test |
| public void testDxCommandNoOptimizeForceJumbo() { |
| // Context with --verbose 2. |
| ExecutionContext context = createExecutionContext(2); |
| Function<Path, Path> pathAbsolutifier = context.getProjectFilesystem().getAbsolutifier(); |
| |
| DxStep dx = new DxStep(SAMPLE_OUTPUT_PATH.toString(), |
| SAMPLE_FILES_TO_DEX, |
| EnumSet.of(DxStep.Option.NO_OPTIMIZE, DxStep.Option.FORCE_JUMBO)); |
| |
| String expected = String.format( |
| "%s --no-optimize --force-jumbo --output %s %s", |
| EXPECTED_DX_PREFIX, |
| SAMPLE_OUTPUT_PATH, |
| Joiner.on(' ').join(Iterables.transform(SAMPLE_FILES_TO_DEX, pathAbsolutifier))); |
| MoreAsserts.assertShellCommands( |
| "Both --no-optimize and --force-jumbo should be present.", |
| ImmutableList.of(expected), |
| ImmutableList.<Step>of(dx), |
| context); |
| verifyAll(); |
| } |
| |
| @Test |
| public void testVerbose3AddsStatisticsFlag() { |
| // Context with --verbose 3. |
| ExecutionContext context = createExecutionContext(3); |
| Function<Path, Path> pathAbsolutifier = context.getProjectFilesystem().getAbsolutifier(); |
| |
| DxStep dx = new DxStep(SAMPLE_OUTPUT_PATH.toString(), SAMPLE_FILES_TO_DEX); |
| |
| String expected = String.format("%s --statistics --output %s %s", |
| EXPECTED_DX_PREFIX, |
| SAMPLE_OUTPUT_PATH, |
| Joiner.on(' ').join(Iterables.transform(SAMPLE_FILES_TO_DEX, pathAbsolutifier))); |
| MoreAsserts.assertShellCommands( |
| "Ensure that the --statistics flag is present.", |
| ImmutableList.of(expected), |
| ImmutableList.<Step>of(dx), |
| context); |
| |
| assertTrue("Should print stdout to show statistics.", |
| dx.shouldPrintStdout(context.getVerbosity())); |
| assertTrue("Should print stderr to show statistics.", |
| dx.shouldPrintStderr(context.getVerbosity())); |
| verifyAll(); |
| } |
| |
| @Test |
| public void testVerbose10AddsVerboseFlagToDx() { |
| // Context with --verbose 10. |
| ExecutionContext context = createExecutionContext(10); |
| Function<Path, Path> pathAbsolutifier = context.getProjectFilesystem().getAbsolutifier(); |
| |
| DxStep dx = new DxStep(SAMPLE_OUTPUT_PATH.toString(), SAMPLE_FILES_TO_DEX); |
| |
| String expected = String.format( |
| "%s --statistics --verbose --output %s %s", |
| EXPECTED_DX_PREFIX, |
| SAMPLE_OUTPUT_PATH, |
| Joiner.on(' ').join(Iterables.transform(SAMPLE_FILES_TO_DEX, pathAbsolutifier))); |
| MoreAsserts.assertShellCommands( |
| "Ensure that the --statistics flag is present.", |
| ImmutableList.of(expected), |
| ImmutableList.<Step>of(dx), |
| context); |
| |
| assertTrue("Should print stdout since `dx --verbose` is enabled.", |
| dx.shouldPrintStdout(context.getVerbosity())); |
| assertTrue("Should print stdout since `dx --verbose` is enabled.", |
| dx.shouldPrintStderr(context.getVerbosity())); |
| verifyAll(); |
| } |
| |
| @Test |
| public void testUseCustomDxOption() { |
| // Context with --verbose 2. |
| ExecutionContext context = createExecutionContext(2); |
| Function<Path, Path> pathAbsolutifier = context.getProjectFilesystem().getAbsolutifier(); |
| |
| DxStep dx = new DxStep(SAMPLE_OUTPUT_PATH.toString(), |
| SAMPLE_FILES_TO_DEX, |
| EnumSet.of(Option.USE_CUSTOM_DX_IF_AVAILABLE), |
| new Supplier<String>() { |
| @Override |
| public String get() { |
| return "/home/mbolin/dx"; |
| } |
| }); |
| |
| String expected = String.format("%s --output %s %s", |
| EXPECTED_DX_PREFIX.replace("/usr/bin/dx", "/home/mbolin/dx"), |
| SAMPLE_OUTPUT_PATH, |
| Joiner.on(' ').join(Iterables.transform(SAMPLE_FILES_TO_DEX, pathAbsolutifier))); |
| MoreAsserts.assertShellCommands( |
| "/home/mbolin/dx should be used instead of /usr/bin/dx.", |
| ImmutableList.of(expected), |
| ImmutableList.<Step>of(dx), |
| context); |
| verifyAll(); |
| } |
| |
| @Test |
| public void testUseCustomDxOptionWithNullSupplier() { |
| // Context with --verbose 2. |
| ExecutionContext context = createExecutionContext(2); |
| Function<Path, Path> pathAbsolutifier = context.getProjectFilesystem().getAbsolutifier(); |
| |
| DxStep dx = new DxStep(SAMPLE_OUTPUT_PATH.toString(), |
| SAMPLE_FILES_TO_DEX, |
| EnumSet.of(Option.USE_CUSTOM_DX_IF_AVAILABLE), |
| new Supplier<String>() { |
| @Override |
| public String get() { |
| return null; |
| } |
| }); |
| |
| String expected = String.format("%s --output %s %s", |
| EXPECTED_DX_PREFIX, |
| SAMPLE_OUTPUT_PATH, |
| Joiner.on(' ').join(Iterables.transform(SAMPLE_FILES_TO_DEX, pathAbsolutifier))); |
| MoreAsserts.assertShellCommands( |
| "Should fall back to /usr/bin/dx even though USE_CUSTOM_DX_IF_AVAILABLE is used.", |
| ImmutableList.of(expected), |
| ImmutableList.<Step>of(dx), |
| context); |
| verifyAll(); |
| } |
| |
| private ExecutionContext createExecutionContext(int verbosityLevel) { |
| TestConsole console = new TestConsole(); |
| Verbosity verbosity = VerbosityParser.getVerbosityForLevel(verbosityLevel); |
| console.setVerbosity(verbosity); |
| return TestExecutionContext.newBuilder() |
| .setConsole(console) |
| .setAndroidPlatformTarget(androidPlatformTargetOptional) |
| .build(); |
| } |
| } |