@Test
  public void testAppleLibraryExportedHeaderSymlinkTree() throws IOException {
    assumeTrue(Platform.detect() == Platform.MACOS);

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

    BuildTarget buildTarget =
        BuildTargetFactory.newInstance(
            "//Libraries/TestLibrary:TestLibrary#"
                + "default,"
                + CxxDescriptionEnhancer.EXPORTED_HEADER_SYMLINK_TREE_FLAVOR);
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", buildTarget.getFullyQualifiedName());
    result.assertSuccess();

    Path inputPath = workspace.getPath(buildTarget.getBasePath()).toRealPath();
    Path outputPath =
        workspace.getPath(BuildTargets.getGenPath(filesystem, buildTarget, "%s")).toRealPath();

    assertIsSymbolicLink(
        outputPath.resolve("TestLibrary/PublicHeader.h"), inputPath.resolve("PublicHeader.h"));
  }
  @Test
  public void compilationDatabaseFetchedFromCacheAlsoFetchesSymlinkTreeOrHeaderMap()
      throws IOException {
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "compilation_database", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new FakeProjectFilesystem();

    // This test only fails if the directory cache is enabled and we don't update
    // the header map/symlink tree correctly when fetching from the cache.
    workspace.enableDirCache();

    addLibraryHeaderFiles(workspace);

    BuildTarget target =
        BuildTargetFactory.newInstance("//:library_with_header#default,compilation-database");

    // Populate the cache with the built rule
    workspace.buildAndReturnOutput(target.getFullyQualifiedName());

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

    // Validate the symlink tree/header maps
    verifyHeaders(workspace, headerSymlinkTreeFolder, "bar.h", "baz.h", "blech_private.h");
    verifyHeaders(workspace, exportedHeaderSymlinkTreeFolder, "bar.h", "baz.h");

    // Delete the newly-added files and build again
    Files.delete(workspace.getPath("baz.h"));
    Files.delete(workspace.getPath("blech_private.h"));
    workspace.buildAndReturnOutput(target.getFullyQualifiedName());
    verifyHeaders(workspace, headerSymlinkTreeFolder, "bar.h");
    verifyHeaders(workspace, exportedHeaderSymlinkTreeFolder, "bar.h");

    // Restore the headers, build again, and check the symlink tree/header maps
    addLibraryHeaderFiles(workspace);
    workspace.buildAndReturnOutput(target.getFullyQualifiedName());
    verifyHeaders(workspace, headerSymlinkTreeFolder, "bar.h", "baz.h", "blech_private.h");
    verifyHeaders(workspace, exportedHeaderSymlinkTreeFolder, "bar.h", "baz.h");
  }
  @Test
  public void sanitizeSymlinkedWorkingDirectory() throws IOException {
    TemporaryFolder folder = new TemporaryFolder();
    folder.create();

    // Setup up a symlink to our working directory.
    Path symlinkedRoot = folder.getRoot().toPath().resolve("symlinked-root");
    java.nio.file.Files.createSymbolicLink(symlinkedRoot, tmp.getRootPath());

    // Run the build, setting PWD to the above symlink.  Typically, this causes compilers to use
    // the symlinked directory, even though it's not the right project root.
    Map<String, String> envCopy = Maps.newHashMap(System.getenv());
    envCopy.put("PWD", symlinkedRoot.toString());
    workspace
        .runBuckCommandWithEnvironmentAndContext(
            tmp.getRootPath(),
            Optional.<NGContext>absent(),
            Optional.<BuckEventListener>absent(),
            Optional.of(ImmutableMap.copyOf(envCopy)),
            "build",
            "//:simple#default,static")
        .assertSuccess();

    // Verify that we still sanitized this path correctly.
    Path lib = workspace.getPath("buck-out/gen/simple#default,static/libsimple.a");
    String contents = Files.asByteSource(lib.toFile()).asCharSource(Charsets.ISO_8859_1).read();
    assertFalse(lib.toString(), contents.contains(tmp.getRootPath().toString()));
    assertFalse(lib.toString(), contents.contains(symlinkedRoot.toString()));

    folder.delete();
  }
  @Test
  public void noIncludeFrameworksDoesntContainFrameworkDependencies() throws Exception {
    assumeTrue(Platform.detect() == Platform.MACOS);
    assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.MACOSX));

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

    BuildTarget target =
        BuildTargetFactory.newInstance(
            "//Libraries/TestLibrary:TestLibrary#"
                + "dwarf-and-dsym,framework,macosx-x86_64,no-include-frameworks");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    Path frameworkPath =
        workspace.getPath(
            BuildTargets.getGenPath(filesystem, target, "%s").resolve("TestLibrary.framework"));
    assertThat(Files.exists(frameworkPath), is(true));
    assertThat(Files.exists(frameworkPath.resolve("Resources/Info.plist")), is(true));
    Path libraryPath = frameworkPath.resolve("TestLibrary");
    assertThat(Files.exists(libraryPath), is(true));
    assertThat(
        workspace.runCommand("file", libraryPath.toString()).getStdout().get(),
        containsString("dynamically linked shared library"));
    Path frameworksPath = frameworkPath.resolve("Contents/Frameworks");
    assertThat(Files.exists(frameworksPath), is(false));
  }
 @Test
 public void sanitizeWorkingDirectory() throws IOException {
   workspace.runBuckBuild("//:simple#default,static").assertSuccess();
   Path lib = workspace.getPath("buck-out/gen/simple#default,static/libsimple.a");
   String contents = Files.asByteSource(lib.toFile()).asCharSource(Charsets.ISO_8859_1).read();
   assertFalse(lib.toString(), contents.contains(tmp.getRootPath().toString()));
 }
  @Test
  public void testAppleLibraryBuildsFramework() throws Exception {
    assumeTrue(Platform.detect() == Platform.MACOS);
    assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.MACOSX));

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

    BuildTarget target =
        BuildTargetFactory.newInstance(
            "//Libraries/TestLibrary:TestLibrary#framework,macosx-x86_64,no-debug");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    Path frameworkPath =
        workspace.getPath(
            BuildTargets.getGenPath(
                    filesystem,
                    BuildTarget.builder(target)
                        .addFlavors(AppleDescriptions.INCLUDE_FRAMEWORKS_FLAVOR)
                        .build(),
                    "%s")
                .resolve("TestLibrary.framework"));
    assertThat(Files.exists(frameworkPath), is(true));
    assertThat(Files.exists(frameworkPath.resolve("Resources/Info.plist")), is(true));
    Path libraryPath = frameworkPath.resolve("TestLibrary");
    assertThat(Files.exists(libraryPath), is(true));
    assertThat(
        workspace.runCommand("file", libraryPath.toString()).getStdout().get(),
        containsString("dynamically linked shared library"));
  }
  @Test
  public void frameworkDependenciesDoNotContainTransitiveDependencies() throws Exception {
    assumeTrue(Platform.detect() == Platform.MACOS);
    assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.MACOSX));

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

    BuildTarget target =
        BuildTargetFactory.newInstance(
            "//Libraries/TestLibrary:TestLibrary#framework,macosx-x86_64");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    Path frameworkPath =
        workspace.getPath(
            BuildTargets.getGenPath(
                    filesystem,
                    BuildTarget.builder(target)
                        .addFlavors(AppleDebugFormat.DWARF.getFlavor())
                        .addFlavors(AppleDescriptions.INCLUDE_FRAMEWORKS_FLAVOR)
                        .build(),
                    "%s")
                .resolve("TestLibrary.framework"));
    assertThat(Files.exists(frameworkPath), is(true));
    Path frameworksPath = frameworkPath.resolve("Frameworks");
    assertThat(Files.exists(frameworksPath), is(true));
    Path depFrameworksPath = frameworksPath.resolve("TestLibraryDep.framework/Frameworks");
    assertThat(Files.exists(depFrameworksPath), is(false));
  }
 private void verifyHeaders(ProjectWorkspace projectWorkspace, Path path, String... headers)
     throws IOException {
   Path resolvedPath = headerSymlinkTreePath(path);
   if (PREPROCESSOR_SUPPORTS_HEADER_MAPS) {
     final List<String> presentHeaders = new ArrayList<>();
     HeaderMap headerMap = HeaderMap.loadFromFile(projectWorkspace.getPath(resolvedPath).toFile());
     headerMap.visit(
         new HeaderMap.HeaderMapVisitor() {
           @Override
           public void apply(String str, String prefix, String suffix) {
             presentHeaders.add(str);
           }
         });
     assertThat(presentHeaders, containsInAnyOrder(headers));
   } else {
     for (String header : headers) {
       assertThat(Files.exists(projectWorkspace.getPath(resolvedPath.resolve(header))), is(true));
     }
   }
 }
  @Test
  public void whenBuckBuiltTwiceLogIsPresent() throws IOException, InterruptedException {
    AssumeAndroidPlatform.assumeSdkIsAvailable();
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "file_watching", tmp);
    workspace.setUp();

    workspace.runBuckdCommand("build", "//java/com/example/activity:activity").assertSuccess();

    Path buildLogFile = workspace.getPath("buck-out/bin/build.log");

    assertTrue(Files.isRegularFile(buildLogFile));
    Files.delete(buildLogFile);

    ProcessResult rebuild =
        workspace.runBuckdCommand("build", "//java/com/example/activity:activity");
    rebuild.assertSuccess();

    buildLogFile = workspace.getPath("buck-out/bin/build.log");
    assertTrue(Files.isRegularFile(buildLogFile));
  }
  @Test
  public void testNativeExopackageHasNoNativeLibraries() throws IOException {
    ZipInspector zipInspector =
        new ZipInspector(workspace.getPath("buck-out/gen/apps/multidex/app-native-exo.apk"));

    zipInspector.assertFileDoesNotExist("assets/secondary-program-dex-jars/metadata.txt");

    zipInspector.assertFileExists("classes2.dex");

    zipInspector.assertFileExists("classes.dex");

    assertNativeLibrariesDontExist(zipInspector);
  }
  @Test
  public void testFlavoredBundleOutputDoesNotContainJSAndResources() throws IOException {
    workspace
        .runBuckBuild("//:DemoApp#iphonesimulator-x86_64,rn_no_bundle,no-debug")
        .assertSuccess();

    Path appDir =
        workspace.getPath(
            "buck-out/gen/DemoApp#iphonesimulator-x86_64,no-debug,rn_no_bundle/DemoApp.app");
    assertTrue(Files.isDirectory(appDir));

    Path bundle = appDir.resolve("Apps/DemoApp/DemoApp.bundle");
    assertFalse(Files.exists(bundle));
  }
  @Test
  public void whenActivityBuckFileRemovedThenRebuildFails()
      throws IOException, InterruptedException {
    AssumeAndroidPlatform.assumeSdkIsAvailable();
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "file_watching", tmp);
    workspace.setUp();

    workspace.runBuckdCommand("build", "//java/com/example/activity:activity").assertSuccess();

    String fileName = "java/com/example/activity/BUCK";
    Files.delete(workspace.getPath(fileName));

    workspace.runBuckdCommand("build", "//java/com/example/activity:activity").assertFailure();
  }
  @Test
  public void whenAppBuckFileRemovedThenRebuildFails() throws IOException, InterruptedException {
    AssumeAndroidPlatform.assumeSdkIsAvailable();

    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "file_watching", tmp);
    workspace.setUp();

    ProcessResult result = workspace.runBuckdCommand("build", "app");
    result.assertSuccess();

    String fileName = "apps/myapp/BUCK";
    Files.delete(workspace.getPath(fileName));

    workspace.runBuckdCommand("build", "app").assertFailure();
  }
  @Test
  public void testAppleLibraryBuildsSomething() throws IOException {
    assumeTrue(Platform.detect() == Platform.MACOS);
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "apple_library_builds_something", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());

    BuildTarget target =
        BuildTargetFactory.newInstance("//Libraries/TestLibrary:TestLibrary#static,default");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    assertTrue(Files.exists(workspace.getPath(BuildTargets.getGenPath(filesystem, target, "%s"))));
  }
  @Test
  public void testBuildEmptySourceAppleLibrary() throws Exception {
    assumeTrue(Platform.detect() == Platform.MACOS);

    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "empty_source_targets", tmp);
    workspace.setUp();
    BuildTarget target = workspace.newBuildTarget("//:real-none#iphonesimulator-x86_64,shared");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
    Path binaryOutput =
        workspace.getPath(BuildTargets.getGenPath(filesystem, target, "%s/libreal-none.dylib"));
    assertThat(Files.exists(binaryOutput), is(true));
  }
  @Test
  public void testInferCxxBinaryWithCachedDepsGetsAllItsTransitiveDeps() throws IOException {
    assumeTrue(Platform.detect() != Platform.WINDOWS);
    ProjectWorkspace workspace = InferHelper.setupCxxInferWorkspace(this, tmp);
    workspace.enableDirCache(); // enable the cache

    BuildTarget inputBuildTarget = BuildTargetFactory.newInstance("//foo:binary_with_chain_deps");
    String inputBuildTargetName =
        inputBuildTarget.withFlavors(CxxInferEnhancer.INFER).getFullyQualifiedName();

    /*
     * Build the given target and check that it succeeds.
     */
    workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess();

    /*
     * Check that building after clean will use the cache
     */
    workspace.runBuckCommand("clean").assertSuccess();
    workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess();
    BuckBuildLog buildLog = workspace.getBuildLog();
    for (BuildTarget buildTarget : buildLog.getAllTargets()) {
      buildLog.assertTargetWasFetchedFromCache(buildTarget.toString());
    }

    /*
     * Check that if the file in the top target changes, then all the transitive deps will be
     * fetched from the cache (even those that are not direct dependencies).
     * Make sure there's the specs file of the dependency that has distance 2 from
     * the binary target.
     */
    String sourceName = "top_chain.c";
    workspace.replaceFileContents("foo/" + sourceName, "*p += 1", "*p += 10");
    workspace.runBuckCommand("clean").assertSuccess();
    workspace.runBuckCommand("build", inputBuildTargetName).assertSuccess();

    // Check all the buildrules were fetched from the cache (and there's the specs file)
    assertTrue(
        "Expected specs file for func_ret_null() in chain_dep_two.c not found",
        workspace
            .getPath(
                "buck-out/gen/foo/infer-analysis-chain_dep_two#default,infer-analyze/specs/"
                    + "mockedSpec.specs")
            .toFile()
            .exists());
  }
  @Test
  public void testAllExopackageHasNeitherSecondaryNorNativeLibraries() throws IOException {
    ZipInspector zipInspector =
        new ZipInspector(
            workspace.getPath(
                BuildTargets.getGenPath(
                    filesystem,
                    BuildTargetFactory.newInstance(DEX_AND_NATIVE_EXOPACKAGE_TARGET),
                    "%s.apk")));

    zipInspector.assertFileDoesNotExist("assets/secondary-program-dex-jars/metadata.txt");
    zipInspector.assertFileDoesNotExist("classes2.dex");

    zipInspector.assertFileExists("classes.dex");

    assertNativeLibrariesDontExist(zipInspector);
  }
  @Test
  public void compilationDatabaseWithDepsFetchedFromCacheAlsoFetchesSymlinkTreeOrHeaderMapOfDeps()
      throws IOException {
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "compilation_database_with_deps", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new FakeProjectFilesystem();

    // This test only fails if the directory cache is enabled and we don't update
    // the header map/symlink tree correctly when fetching from the cache.
    workspace.enableDirCache();

    addDepLibraryHeaderFiles(workspace);

    BuildTarget target =
        BuildTargetFactory.newInstance("//:library_with_header#default,compilation-database");

    // Populate the cache with the built rule
    workspace.buildAndReturnOutput(target.getFullyQualifiedName());

    Path dep1ExportedSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem, BuildTargetFactory.newInstance("//dep1:dep1#default,headers"), "%s");
    Path dep2ExportedSymlinkTreeFolder =
        BuildTargets.getGenPath(
            filesystem, BuildTargetFactory.newInstance("//dep2:dep2#default,headers"), "%s");

    // Validate the deps' symlink tree/header maps
    verifyHeaders(workspace, dep1ExportedSymlinkTreeFolder, "dep1/dep1.h", "dep1/dep1_new.h");
    verifyHeaders(workspace, dep2ExportedSymlinkTreeFolder, "dep2/dep2.h", "dep2/dep2_new.h");

    // Delete the newly-added files and build again
    Files.delete(workspace.getPath("dep1/dep1_new.h"));
    Files.delete(workspace.getPath("dep2/dep2_new.h"));
    workspace.buildAndReturnOutput(target.getFullyQualifiedName());
    verifyHeaders(workspace, dep1ExportedSymlinkTreeFolder, "dep1/dep1.h");
    verifyHeaders(workspace, dep2ExportedSymlinkTreeFolder, "dep2/dep2.h");

    // Restore the headers, build again, and check the deps' symlink tree/header maps
    addDepLibraryHeaderFiles(workspace);
    workspace.buildAndReturnOutput(target.getFullyQualifiedName());
    verifyHeaders(workspace, dep1ExportedSymlinkTreeFolder, "dep1/dep1.h", "dep1/dep1_new.h");
    verifyHeaders(workspace, dep2ExportedSymlinkTreeFolder, "dep2/dep2.h", "dep2/dep2_new.h");
  }
  @Test
  public void whenSourceInputInvalidatedThenRebuildFails()
      throws IOException, InterruptedException {
    AssumeAndroidPlatform.assumeSdkIsAvailable();
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "file_watching", tmp);
    workspace.setUp();

    workspace.runBuckdCommand("build", "//java/com/example/activity:activity").assertSuccess();

    String fileName = "java/com/example/activity/MyFirstActivity.java";
    Files.delete(workspace.getPath(fileName));

    thrown.expect(HumanReadableException.class);
    thrown.expectMessage(containsString("MyFirstActivity.java"));

    workspace.runBuckdCommand("build", "//java/com/example/activity:activity");
  }
  @Test
  public void testKeepGoingWithOneFailingTarget() throws IOException {
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "keep_going", tmp).setUp();

    ProcessResult result =
        workspace
            .runBuckBuild("--keep-going", "//:rule_with_output", "//:failing_rule")
            .assertFailure();
    String expectedReport =
        "OK   //:rule_with_output BUILT_LOCALLY "
            + GENRULE_OUTPUT
            + "\n"
            + "FAIL //:failing_rule\n";
    assertThat(result.getStderr(), containsString(expectedReport));
    Path outputFile = workspace.getPath(GENRULE_OUTPUT);
    assertTrue(Files.exists(outputFile));
  }
  @Test
  public void testAppleLibraryBuildsForWatchOS() throws IOException {
    assumeTrue(AppleNativeIntegrationTestUtils.isApplePlatformAvailable(ApplePlatform.WATCHOS));

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

    BuildTarget target =
        BuildTargetFactory.newInstance("//Libraries/TestLibrary:TestLibrary#watchos-armv7k,static");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    assertTrue(Files.exists(workspace.getPath(BuildTargets.getGenPath(filesystem, target, "%s"))));
  }
  @Test
  public void testAppleLibraryWithDefaultsInRuleBuildsSomething() throws IOException {
    assumeTrue(Platform.detect() == Platform.MACOS);
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "apple_library_with_platform_and_type", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());

    BuildTarget target = BuildTargetFactory.newInstance("//Libraries/TestLibrary:TestLibrary");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    BuildTarget implicitTarget =
        target.withAppendedFlavors(
            ImmutableFlavor.of("shared"), ImmutableFlavor.of("iphoneos-arm64"));
    Path outputPath = workspace.getPath(BuildTargets.getGenPath(filesystem, implicitTarget, "%s"));
    assertTrue(Files.exists(outputPath));
  }
  @Test
  public void whenAppBuckFileInvalidatedThenRebuildFails()
      throws IOException, InterruptedException {
    AssumeAndroidPlatform.assumeSdkIsAvailable();
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "file_watching", tmp);
    workspace.setUp();

    workspace.runBuckdCommand("build", "app").assertSuccess();

    String fileName = "apps/myapp/BUCK";
    Files.write(workspace.getPath(fileName), "Some Illegal Python".getBytes(Charsets.US_ASCII));

    ProcessResult result = workspace.runBuckdCommand("build", "app");
    assertThat(
        "Failure should be due to syntax error.",
        result.getStderr(),
        containsString("SyntaxError: invalid syntax"));
    result.assertFailure();
  }
  @Test
  public void testBuildAppleLibraryThatHasSwift() throws Exception {
    assumeTrue(Platform.detect() == Platform.MACOS);

    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "empty_source_targets", tmp);
    workspace.setUp();
    BuildTarget target = workspace.newBuildTarget("//:none-swift#iphonesimulator-x86_64,shared");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
    Path binaryOutput =
        workspace.getPath(BuildTargets.getGenPath(filesystem, target, "%s/libnone-swift.dylib"));
    assertThat(Files.exists(binaryOutput), is(true));

    assertThat(
        workspace.runCommand("otool", "-L", binaryOutput.toString()).getStdout().get(),
        containsString("libswiftCore.dylib"));
  }
  @Test
  public void testDexExopackageHasNoSecondary() throws IOException {
    ZipInspector zipInspector =
        new ZipInspector(
            workspace.getPath(
                BuildTargets.getGenPath(
                    filesystem, BuildTargetFactory.newInstance(DEX_EXOPACKAGE_TARGET), "%s.apk")));
    zipInspector.assertFileDoesNotExist("assets/secondary-program-dex-jars/metadata.txt");
    zipInspector.assertFileDoesNotExist("assets/secondary-program-dex-jars/secondary-1.dex.jar");
    zipInspector.assertFileDoesNotExist("classes2.dex");

    zipInspector.assertFileExists("classes.dex");
    zipInspector.assertFileExists("lib/armeabi/libfakenative.so");

    // It would be better if we could call getExopackageInfo on the app rule.
    Path secondaryDir =
        workspace.resolve(
            BuildTargets.getScratchPath(
                filesystem,
                BuildTargetFactory.newInstance(DEX_EXOPACKAGE_TARGET)
                    .withFlavors(ImmutableFlavor.of("dex_merge")),
                "_%s_output/jarfiles/assets/secondary-program-dex-jars"));

    try (DirectoryStream<Path> stream = Files.newDirectoryStream(secondaryDir)) {
      List<Path> files = Lists.newArrayList(stream);
      assertEquals(2, files.size());
      Collections.sort(files);

      Path secondaryJar = files.get(0);
      ZipInspector zi = new ZipInspector(secondaryJar);
      zi.assertFileExists("classes.dex");
      long jarSize = Files.size(secondaryJar);
      long classesDexSize = zi.getSize("classes.dex");

      Path dexMeta = files.get(1);
      assertEquals(
          String.format("jar:%s dex:%s", jarSize, classesDexSize),
          new String(Files.readAllBytes(dexMeta), "US-ASCII"));
    }
  }
  @Test
  public void whenSourceInputRemovedThenRebuildFails() throws IOException, InterruptedException {
    AssumeAndroidPlatform.assumeNdkIsAvailable();
    final ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "file_watching", tmp);
    workspace.setUp();

    workspace.runBuckdCommand("build", "//java/com/example/activity:activity").assertSuccess();

    String fileName = "java/com/example/activity/MyFirstActivity.java";
    Files.delete(workspace.getPath(fileName));

    try {
      workspace.runBuckdCommand("build", "//java/com/example/activity:activity");
      fail("Should have thrown HumanReadableException.");
    } catch (java.lang.RuntimeException e) {
      assertThat(
          "Failure should have been due to file removal.",
          e.getMessage(),
          containsString("MyFirstActivity.java"));
    }
  }
  @Test
  public void shouldSerializeEventsToFile() throws IOException {
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "simple_project", temporaryFolder);
    workspace.setUp();

    Path eventsOutputFile = workspace.getPath("events.json");

    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand(
            "test",
            "--all",
            "--output-test-events-to-file",
            eventsOutputFile.toAbsolutePath().toString());
    result.assertSuccess();

    List<String> lines = Files.readAllLines(eventsOutputFile, StandardCharsets.UTF_8);
    assertFalse("The events output file should not be empty", lines.isEmpty());
    assertThat(
        "An event should have something JSON-like in it",
        lines.get(0),
        containsString("\"timestamp\":"));
  }
  @Test
  public void testAppleLibraryWithDefaultsInConfigBuildsSomething() throws IOException {
    assumeTrue(Platform.detect() == Platform.MACOS);
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(
            this, "apple_library_builds_something", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());
    workspace.writeContentsToPath(
        "[defaults.apple_library]\n  platform = iphonesimulator-x86_64\n  type = shared\n",
        ".buckconfig.local");

    BuildTarget target = BuildTargetFactory.newInstance("//Libraries/TestLibrary:TestLibrary");
    ProjectWorkspace.ProcessResult result =
        workspace.runBuckCommand("build", target.getFullyQualifiedName());
    result.assertSuccess();

    BuildTarget implicitTarget =
        target.withAppendedFlavors(
            ImmutableFlavor.of("shared"), ImmutableFlavor.of("iphonesimulator-x86_64"));
    assertTrue(
        Files.exists(workspace.getPath(BuildTargets.getGenPath(filesystem, implicitTarget, "%s"))));
  }
  @Test
  public void testAppleLibraryIsHermetic() throws IOException {
    assumeTrue(Platform.detect() == Platform.MACOS);
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "apple_library_is_hermetic", tmp);
    workspace.setUp();
    ProjectFilesystem filesystem = new ProjectFilesystem(workspace.getDestPath());

    BuildTarget target =
        BuildTargetFactory.newInstance(
            "//Libraries/TestLibrary:TestLibrary#static,iphonesimulator-x86_64");
    ProjectWorkspace.ProcessResult first =
        workspace.runBuckCommand(
            workspace.getPath("first"), "build", target.getFullyQualifiedName());
    first.assertSuccess();

    ProjectWorkspace.ProcessResult second =
        workspace.runBuckCommand(
            workspace.getPath("second"), "build", target.getFullyQualifiedName());
    second.assertSuccess();

    Path objectPath =
        BuildTargets.getGenPath(
                filesystem,
                target.withFlavors(
                    ImmutableFlavor.of("compile-" + sanitize("TestClass.m.o")),
                    ImmutableFlavor.of("iphonesimulator-x86_64")),
                "%s")
            .resolve("TestClass.m.o");
    MoreAsserts.assertContentsEqual(
        workspace.getPath(Paths.get("first").resolve(objectPath)),
        workspace.getPath(Paths.get("second").resolve(objectPath)));
    Path libraryPath =
        BuildTargets.getGenPath(filesystem, target, "%s").resolve("libTestLibrary.a");
    MoreAsserts.assertContentsEqual(
        workspace.getPath(Paths.get("first").resolve(libraryPath)),
        workspace.getPath(Paths.get("second").resolve(libraryPath)));
  }
  @Test
  public void testAppleLibraryIsHermetic() throws IOException {
    assumeTrue(Platform.detect() == Platform.MACOS);
    ProjectWorkspace workspace =
        TestDataHelper.createProjectWorkspaceForScenario(this, "apple_library_is_hermetic", tmp);
    workspace.setUp();

    ProjectWorkspace.ProcessResult first =
        workspace.runBuckCommand(
            workspace.getPath("first"),
            "build",
            "//Libraries/TestLibrary:TestLibrary#static,iphonesimulator-x86_64");
    first.assertSuccess();

    ProjectWorkspace.ProcessResult second =
        workspace.runBuckCommand(
            workspace.getPath("second"),
            "build",
            "//Libraries/TestLibrary:TestLibrary#static,iphonesimulator-x86_64");
    second.assertSuccess();

    MoreAsserts.assertContentsEqual(
        workspace.getPath(
            "first/buck-out/gen/Libraries/TestLibrary/"
                + "TestLibrary#compile-TestClass.m.o,iphonesimulator-x86_64/TestClass.m.o"),
        workspace.getPath(
            "second/buck-out/gen/Libraries/TestLibrary/"
                + "TestLibrary#compile-TestClass.m.o,iphonesimulator-x86_64/TestClass.m.o"));
    MoreAsserts.assertContentsEqual(
        workspace.getPath(
            "first/buck-out/gen/Libraries/TestLibrary/"
                + "TestLibrary#iphonesimulator-x86_64,static/libTestLibrary.a"),
        workspace.getPath(
            "second/buck-out/gen/Libraries/TestLibrary/"
                + "TestLibrary#iphonesimulator-x86_64,static/libTestLibrary.a"));
  }