blob: ed5f5cef9940dd137c67ce41d38f187829873502 [file] [log] [blame]
/*
* 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.cli;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import com.facebook.buck.testutil.integration.DebuggableTemporaryFolder;
import com.facebook.buck.testutil.integration.ProjectWorkspace;
import com.facebook.buck.testutil.integration.ProjectWorkspace.ProcessResult;
import com.facebook.buck.testutil.integration.TestDataHelper;
import com.facebook.buck.util.HumanReadableException;
import com.google.common.base.CharMatcher;
import com.google.common.base.Charsets;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Files;
import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.io.IOException;
public class TargetsCommandIntegrationTest {
private static final String ABSOLUTE_PATH_TO_FILE_OUTSIDE_THE_PROJECT_THAT_EXISTS_ON_THE_FS =
"/bin/sh";
private static final CharMatcher LOWER_CASE_HEX_DIGITS =
CharMatcher.inRange('0', '9').or(CharMatcher.inRange('a', 'f'));
@Rule
public DebuggableTemporaryFolder tmp = new DebuggableTemporaryFolder();
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void testOutputPath() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "output_path", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand(
"targets",
"--show_output",
"//:test");
result.assertSuccess();
assertEquals("//:test buck-out/gen/test-output\n", result.getStdout());
}
@Test
public void testRuleKey() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "output_path", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand(
"targets",
"--show_rulekey",
"//:test");
result.assertSuccess();
assertEquals("//:test 79fd7645a0ee301307d83049da0ba75f46f7fef3\n", result.getStdout());
}
@Test
public void testBothOutputAndRuleKey() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "output_path", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand(
"targets",
"--show_rulekey",
"--show_output",
"//:test");
result.assertSuccess();
assertEquals(
"//:test 79fd7645a0ee301307d83049da0ba75f46f7fef3 buck-out/gen/test-output\n",
result.getStdout());
}
@Test
public void testOutputWithoutTarget() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "output_path", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand(
"targets",
"--show_output");
result.assertFailure();
assertEquals("BUILD FAILED: Must specify at least one build target.\n", result.getStderr());
}
@Test
public void testRuleKeyWithoutTarget() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "output_path", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand(
"targets",
"--show_rulekey");
result.assertFailure();
assertEquals("BUILD FAILED: Must specify at least one build target.\n", result.getStderr());
}
private String parseAndVerifyTargetAndHash(String target, String outputLine) {
List<String> targetAndHash = Splitter.on(' ').splitToList(
CharMatcher.WHITESPACE.trimFrom(outputLine));
assertEquals(2, targetAndHash.size());
assertEquals(target, targetAndHash.get(0));
assertFalse(targetAndHash.get(1).isEmpty());
assertTrue(LOWER_CASE_HEX_DIGITS.matchesAllOf(targetAndHash.get(1)));
return targetAndHash.get(1);
}
@Test
public void testTargetHash() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "output_path", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand(
"targets",
"--show-target-hash",
"//:test");
result.assertSuccess();
parseAndVerifyTargetAndHash(
"//:test",
result.getStdout());
}
@Test
public void testTargetHashAndRuleKeyThrows() throws IOException {
thrown.expect(HumanReadableException.class);
thrown.expectMessage("Cannot show rule key and target hash at the same time.");
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "output_path", tmp);
workspace.setUp();
workspace.runBuckCommand(
"targets",
"--show-target-hash",
"--show-rulekey",
"//:test");
}
@Test
public void testTargetHashAndRuleKeyAndOutputThrows() throws IOException {
thrown.expect(HumanReadableException.class);
thrown.expectMessage("Cannot show rule key and target hash at the same time.");
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "output_path", tmp);
workspace.setUp();
workspace.runBuckCommand(
"targets",
"--show-target-hash",
"--show-rulekey",
"--show-output",
"//:test");
}
@Test
public void testTargetHashXcodeWorkspaceWithTests() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "xcode_workspace_with_tests", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand(
"targets",
"--show-target-hash",
"--detect-test-changes",
"//workspace:workspace");
result.assertSuccess();
parseAndVerifyTargetAndHash("//workspace:workspace", result.getStdout());
}
@Test
public void testTargetHashXcodeWorkspaceWithoutTestsDiffersFromWithTests() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "xcode_workspace_with_tests", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand(
"targets",
"--show-target-hash",
"--detect-test-changes",
"//workspace:workspace");
result.assertSuccess();
String hash = parseAndVerifyTargetAndHash("//workspace:workspace", result.getStdout());
ProcessResult result2 = workspace.runBuckCommand(
"targets",
"--show-target-hash",
"//workspace:workspace");
result2.assertSuccess();
String hash2 = parseAndVerifyTargetAndHash("//workspace:workspace", result2.getStdout());
assertNotEquals(hash, hash2);
}
@Test
public void testTargetHashChangesAfterModifyingSourceFile() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "xcode_workspace_with_tests", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand(
"targets",
"--show-target-hash",
"--detect-test-changes",
"//workspace:workspace");
result.assertSuccess();
String hash = parseAndVerifyTargetAndHash(
"//workspace:workspace",
result.getStdout());
String fileName = "test/Test.m";
Files.write("// This is not a test\n".getBytes(Charsets.UTF_8), workspace.getFile(fileName));
ProcessResult result2 = workspace.runBuckCommand(
"targets",
"--show-target-hash",
"--detect-test-changes",
"//workspace:workspace");
result2.assertSuccess();
String hash2 = parseAndVerifyTargetAndHash(
"//workspace:workspace",
result2.getStdout());
assertNotEquals(hash, hash2);
}
@Test
public void testTargetHashChangesAfterDeletingSourceFile() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "xcode_workspace_with_tests", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand(
"targets",
"--show-target-hash",
"--detect-test-changes",
"//workspace:workspace");
result.assertSuccess();
String hash = parseAndVerifyTargetAndHash(
"//workspace:workspace",
result.getStdout());
String fileName = "test/Test.m";
workspace.getFile(fileName).delete();
ProcessResult result2 = workspace.runBuckCommand(
"targets",
"--show-target-hash",
"--detect-test-changes",
"//workspace:workspace");
result2.assertSuccess();
String hash2 = parseAndVerifyTargetAndHash(
"//workspace:workspace",
result2.getStdout());
assertNotEquals(hash, hash2);
}
@Test
public void testBuckTargetsReferencedFileWithFileOutsideOfProject() throws IOException {
// The contents of the project are not relevant for this test. We just want a non-empty project
// to prevent against a regression where all of the build rules are printed.
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "project_slice", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand(
"targets",
"--referenced_file",
ABSOLUTE_PATH_TO_FILE_OUTSIDE_THE_PROJECT_THAT_EXISTS_ON_THE_FS);
result.assertSuccess("Even though the file is outside the project, " +
"`buck targets` should succeed.");
assertEquals("Because no targets match, stdout should be empty.", "", result.getStdout());
}
@Test
public void testBuckTargetsReferencedFileWithFilesInAndOutsideOfProject() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "project_slice", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand(
"targets",
"--type",
"prebuilt_jar",
"--referenced_file",
ABSOLUTE_PATH_TO_FILE_OUTSIDE_THE_PROJECT_THAT_EXISTS_ON_THE_FS,
"libs/guava.jar", // relative path in project
tmp.getRootPath().resolve("libs/junit.jar").toString()); // absolute path in project
result.assertSuccess("Even though one referenced file is outside the project, " +
"`buck targets` should succeed.");
assertEquals(
ImmutableSet.of(
"//libs:guava",
"//libs:junit"),
ImmutableSet.copyOf(Splitter.on('\n').omitEmptyStrings().split(result.getStdout())));
}
@Test
public void testBuckTargetsReferencedFileWithNonExistentFile() throws IOException {
// The contents of the project are not relevant for this test. We just want a non-empty project
// to prevent against a regression where all of the build rules are printed.
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "project_slice", tmp);
workspace.setUp();
String pathToNonExistentFile = "modules/dep1/dep2/hello.txt";
assertFalse(workspace.getFile(pathToNonExistentFile).exists());
ProcessResult result = workspace.runBuckCommand(
"targets",
"--referenced_file",
pathToNonExistentFile);
result.assertSuccess("Even though the file does not exist, buck targets` should succeed.");
assertEquals("Because no targets match, stdout should be empty.", "", result.getStdout());
}
@Test
public void testValidateBuildTargetForNonAliasTarget() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(
this, "target_validation", tmp);
workspace.setUp();
ProcessResult result = workspace.runBuckCommand("targets", "--resolvealias", "//:test-library");
assertTrue(result.getStdout(), result.getStdout().contains("//:test-library"));
try {
workspace.runBuckCommand("targets", "--resolvealias", "//:");
} catch (HumanReadableException e) {
assertEquals("//: cannot end with a colon", e.getMessage());
}
try {
workspace.runBuckCommand("targets", "--resolvealias", "//:test-libarry");
} catch (HumanReadableException e) {
assertEquals("//:test-libarry is not a valid target.", e.getMessage());
}
try {
workspace.runBuckCommand("targets", "--resolvealias", "//blah/foo");
} catch (HumanReadableException e) {
assertEquals("//blah/foo must contain exactly one colon (found 0)", e.getMessage());
}
}
}