@Test
  public void testCreateRelativeSymlinkToFilesInRoot() throws IOException {
    ProjectFilesystem projectFilesystem = new ProjectFilesystem(tmp.getRoot());
    tmp.newFile("biz.txt");

    Path pathToDesiredLinkUnderProjectRoot = Paths.get("gamma.txt");
    Path pathToExistingFileUnderProjectRoot = Paths.get("biz.txt");
    Path relativePath =
        MorePaths.createRelativeSymlink(
            pathToDesiredLinkUnderProjectRoot,
            pathToExistingFileUnderProjectRoot,
            projectFilesystem);
    assertEquals("biz.txt", relativePath.toString());

    Path absolutePathToDesiredLinkUnderProjectRoot =
        projectFilesystem.resolve(pathToDesiredLinkUnderProjectRoot);
    assertTrue(Files.isSymbolicLink(absolutePathToDesiredLinkUnderProjectRoot));
    Path targetOfSymbolicLink = Files.readSymbolicLink(absolutePathToDesiredLinkUnderProjectRoot);
    assertEquals(relativePath, targetOfSymbolicLink);

    Path absolutePathToExistingFileUnderProjectRoot =
        projectFilesystem.resolve(pathToExistingFileUnderProjectRoot);
    Files.write(absolutePathToExistingFileUnderProjectRoot, "Hello, World!".getBytes());
    String dataReadFromSymlink =
        new String(Files.readAllBytes(absolutePathToDesiredLinkUnderProjectRoot));
    assertEquals("Hello, World!", dataReadFromSymlink);
  }
  @Test
  public void testAppleDynamicLibraryWithDsym() throws Exception {
    assumeTrue(Platform.detect() == Platform.MACOS);
    assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.MACOSX));

    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "apple_library_shared", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());

    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand(
            "build",
            "//Libraries/TestLibrary:TestLibrary#shared,macosx-x86_64,dwarf-and-dsym",
            "--config",
            "cxx.cflags=-g");
    result.assertSuccess();

    Path output =
        tmp.getRoot()
            .resolve(filesystem.getBuckPaths().getGenDir())
            .resolve("Libraries/TestLibrary/TestLibrary#macosx-x86_64,shared")
            .resolve("libLibraries_TestLibrary_TestLibrary.dylib");
    assertThat(Files.exists(output), is(true));

    Path dsymPath =
        tmp.getRoot()
            .resolve(filesystem.getBuckPaths().getGenDir())
            .resolve("Libraries/TestLibrary")
            .resolve("TestLibrary#apple-dsym,macosx-x86_64,shared.dSYM");
    assertThat(Files.exists(dsymPath), is(true));
    AppleDsymTestUtil.checkDsymFileHasDebugSymbol("+[TestClass answer]", workspace, dsymPath);
  }
  @Test
  public void testUberCompilationDatabase() throws IOException {
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "compilation_database", tmp);
    workspace.setUp();
    BuildTarget target =
        BuildTargetFactory.newInstance("//:test#default,uber-compilation-database");
    ProjectFilesystem filesystem = new FakeProjectFilesystem();
    Path compilationDatabase = workspace.buildAndReturnOutput(target.getFullyQualifiedName());
    Path rootPath = tmp.getRoot();
    assertEquals(
        BuildTargets.getGenPath(
            filesystem, target, "uber-compilation-database-%s/compile_commands.json"),
        rootPath.relativize(compilationDatabase));

    Path binaryHeaderSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem,
            target.withFlavors(
                ImmutableFlavor.of("default"), CxxDescriptionEnhancer.HEADER_SYMLINK_TREE_FLAVOR),
            "%s");
    Path binaryExportedHeaderSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem,
            target.withFlavors(
                ImmutableFlavor.of("default"),
                CxxDescriptionEnhancer.EXPORTED_HEADER_SYMLINK_TREE_FLAVOR),
            "%s");

    Map<String, CxxCompilationDatabaseEntry> fileToEntry =
        CxxCompilationDatabaseUtils.parseCompilationDatabaseJsonFile(compilationDatabase);
    assertEquals(1, fileToEntry.size());
    assertHasEntry(
        fileToEntry,
        "test.cpp",
        new ImmutableList.Builder<String>()
            .add(COMPILER_PATH)
            .add("-fPIC")
            .add("-fPIC")
            .add("-I")
            .add(headerSymlinkTreePath(binaryHeaderSymlinkTreeFolder).toString())
            .add("-I")
            .add(headerSymlinkTreePath(binaryExportedHeaderSymlinkTreeFolder).toString())
            .addAll(getExtraFlagsForHeaderMaps(filesystem))
            .addAll(COMPILER_SPECIFIC_FLAGS)
            .add("-x")
            .add("c++")
            .add("-c")
            .add("-o")
            .add(
                BuildTargets.getGenPath(
                        filesystem,
                        target.withFlavors(
                            ImmutableFlavor.of("default"),
                            ImmutableFlavor.of("compile-pic-" + sanitize("test.cpp.o"))),
                        "%s/test.cpp.o")
                    .toString())
            .add(rootPath.resolve(Paths.get("test.cpp")).toRealPath().toString())
            .build());
  }
 private void assertHasEntry(
     Map<String, CxxCompilationDatabaseEntry> fileToEntry, String fileName, List<String> command)
     throws IOException {
   String key = tmp.getRoot().toRealPath().resolve(fileName).toString();
   CxxCompilationDatabaseEntry entry = fileToEntry.get(key);
   assertNotNull("There should be an entry for " + key + ".", entry);
   assertEquals(
       Joiner.on(' ').join(Iterables.transform(command, Escaper.SHELL_ESCAPER)),
       entry.getCommand());
 }
 @Test
 public void processCwdIsRespected() throws Exception {
   ProcessExecutorParams.Builder paramsBuilder = ProcessExecutorParams.builder();
   if (Platform.detect() == Platform.WINDOWS) {
     paramsBuilder.addCommand("cmd.exe", "/c", "type");
   } else {
     paramsBuilder.addCommand("cat");
   }
   paramsBuilder.addCommand("hello-world.txt");
   paramsBuilder.setDirectory(tmp.getRoot());
   Path helloWorldPath = tmp.getRoot().resolve("hello-world.txt");
   String fileContents = "Hello, world!";
   Files.write(helloWorldPath, fileContents.getBytes(StandardCharsets.UTF_8));
   ListeningProcessExecutor executor = new ListeningProcessExecutor();
   CapturingListener listener = new CapturingListener();
   ListeningProcessExecutor.LaunchedProcess process =
       executor.launchProcess(paramsBuilder.build(), listener);
   int returnCode = executor.waitForProcess(process);
   assertThat(returnCode, equalTo(0));
   assertThat(listener.capturedStdout.toString("UTF-8"), equalTo(fileContents));
   assertThat(listener.capturedStderr.toString("UTF-8"), is(emptyString()));
 }
  @Test
  public void testFilterForSubpaths() {
    Path root = tmp.getRoot();
    ImmutableSortedSet<Path> paths =
        MorePaths.asPaths(
            ImmutableSet.of(
                ".buckd",
                "foo/bar",
                root.toAbsolutePath() + "/buck-cache",
                Paths.get("/root/not/in/test").toAbsolutePath().toString()));

    assertEquals(
        "Set should have been filtered down to paths contained under root.",
        ImmutableSet.of(Paths.get(".buckd"), Paths.get("foo/bar"), Paths.get("buck-cache")),
        MorePaths.filterForSubpaths(paths, root));
  }
 @Before
 public void setUp() throws IOException {
   workspace = new ProjectWorkspace(projectFolderWithPrebuiltTargets.getRoot(), tmpFolder);
   workspace.setUp();
   filesystem = new ProjectFilesystem(workspace.getDestPath());
 }
  @Test
  public void binaryWithDependenciesCompilationDatabase() throws IOException {
    BuildTarget target = BuildTargetFactory.newInstance("//:binary_with_dep#compilation-database");
    Path compilationDatabase = workspace.buildAndReturnOutput(target.getFullyQualifiedName());
    ProjectFilesystem filesystem = new FakeProjectFilesystem();

    Path rootPath = tmp.getRoot();
    assertEquals(
        BuildTargets.getGenPath(filesystem, target, "__%s.json"),
        rootPath.relativize(compilationDatabase));

    Path binaryHeaderSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem,
            target.withFlavors(
                ImmutableFlavor.of("default"), CxxDescriptionEnhancer.HEADER_SYMLINK_TREE_FLAVOR),
            "%s");
    assertTrue(Files.exists(rootPath.resolve(binaryHeaderSymlinkTreeFolder)));

    BuildTarget libraryTarget = BuildTargetFactory.newInstance("//:library_with_header");
    Path libraryExportedHeaderSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem,
            libraryTarget.withFlavors(
                ImmutableFlavor.of("default"),
                CxxDescriptionEnhancer.EXPORTED_HEADER_SYMLINK_TREE_FLAVOR),
            "%s");

    // Verify that symlink folders for headers are created and header file is linked.
    assertTrue(Files.exists(rootPath.resolve(libraryExportedHeaderSymlinkTreeFolder)));
    assertTrue(Files.exists(rootPath.resolve(libraryExportedHeaderSymlinkTreeFolder + "/bar.h")));

    Map<String, CxxCompilationDatabaseEntry> fileToEntry =
        CxxCompilationDatabaseUtils.parseCompilationDatabaseJsonFile(compilationDatabase);
    assertEquals(1, fileToEntry.size());
    assertHasEntry(
        fileToEntry,
        "foo.cpp",
        new ImmutableList.Builder<String>()
            .add(COMPILER_PATH)
            .add("-I")
            .add(headerSymlinkTreePath(binaryHeaderSymlinkTreeFolder).toString())
            .add("-I")
            .add(headerSymlinkTreePath(libraryExportedHeaderSymlinkTreeFolder).toString())
            .addAll(getExtraFlagsForHeaderMaps(filesystem))
            .addAll(COMPILER_SPECIFIC_FLAGS)
            .add("-x")
            .add("c++")
            .add("-c")
            .add("-o")
            .add(
                BuildTargets.getGenPath(
                        filesystem,
                        target.withFlavors(
                            ImmutableFlavor.of("default"),
                            ImmutableFlavor.of("compile-" + sanitize("foo.cpp.o"))),
                        "%s/foo.cpp.o")
                    .toString())
            .add(rootPath.resolve(Paths.get("foo.cpp")).toRealPath().toString())
            .build());
  }