Repository: carbon-language/carbon-lang
File: toolchain/driver/driver_test.cpp (C++)

Code before:

  // Rename it to a flag-like name.
  Filesystem::Cwd().Rename("test.o", Filesystem::Cwd(), "--test.o").Check();

  // Link this into a binary and pass flags to the Clang link invocation even
  // though we use `--` before the object file input list to handle weirdly
  // named objects.
  //
  // TODO: This works correctly in the Carbon link subcommand, but Clang itself
  // fails to pass object files to LLD in a way that supports flag-shaped object
  // file names. The last flag being `-Wl,--` tries to work around this by
  // passing a `--` to the linker before the object files. However, LLD in turn
  // appears to have bugs parsing command lines in this shape. We should get
  // these fixed and then can remove the `-Wl,--` hack and the test should
  // actually pass.
  std::string out;
  std::string err;
  EXPECT_FALSE(CallWithCapturedOutput(out, err, [&] {
                 return driver_.RunCommand({"--no-build-runtimes", "link",
                                            "--output=test", "--", "--test.o",
                                            "--", "-lc", "-lm", "-Wl,--"});
               }).success);
  EXPECT_THAT(test_error_stream_.TakeStr(), StrEq(""));
  EXPECT_THAT(out, StrEq(""));
  // This error seems to stem from incorrectly handling `--` in the LLD command
  // line. See above -- this should go away when the underlying bugs are fixed.
  EXPECT_THAT(err,
              HasSubstr("error: completed parsing all 1 configured positional "
                        "arguments, but found a subsequent `--`"));
}

TEST_F(DriverTest, ConfigJson) {
  EXPECT_TRUE(driver_.RunCommand({"config", "--json"}).success);
  EXPECT_THAT(test_error_stream_.TakeStr(), StrEq(""));

  // Make sure the output parses as JSON.
  std::string output = test_output_stream_.TakeStr();
  llvm::Expected<llvm::json::Value> json_value = llvm::json::parse(output);
  if (auto error = json_value.takeError()) {
    FAIL() << "Unable to parse to JSON: " << toString(std::move(error))
           << "\nOriginal text:\n"
           << output << "\n";
  }
  llvm::json::Object* json_obj = json_value->getAsObject();
  ASSERT_THAT(json_obj, NotNull());

  // Check relevant paths in the output point to existing directories.
  std::optional<llvm::StringRef> install_root =
      json_obj->getString("INSTALL_ROOT");
  ASSERT_THAT(install_root, Ne(std::nullopt));
  EXPECT_THAT(Filesystem::Cwd().OpenDir(install_root->str()), IsSuccess(_));

Review comment (bug):
```suggestion
  // line. See above; this should go away when the underlying bugs are fixed.
```

With all the comments about `--` I *think* this isn't a flag `--` but instead a typographic `--`; I'm going to suggest different punctuation.

Code after:

  // Rename it to a flag-like name.
  Filesystem::Cwd().Rename("test.o", Filesystem::Cwd(), "--test.o").Check();

  // Link this into a binary and pass flags to the Clang link invocation even
  // though we use `--` before the object file input list to handle weirdly
  // named objects.
  //
  // TODO: This works correctly in the Carbon link subcommand, but Clang itself
  // fails to pass object files to LLD in a way that supports flag-shaped object
  // file names. The last flag being `-Wl,--` tries to work around this by
  // passing a `--` to the linker before the object files. However, LLD in turn
  // appears to have bugs parsing command lines in this shape. We should get
  // these fixed and then can remove the `-Wl,--` hack and the test should
  // actually pass.
  std::string out;
  std::string err;
  EXPECT_FALSE(CallWithCapturedOutput(out, err, [&] {
                 return driver_.RunCommand({"--no-build-runtimes", "link",
                                            "--output=test", "--", "--test.o",
                                            "--", "-lc", "-lm", "-Wl,--"});
               }).success);
  EXPECT_THAT(test_error_stream_.TakeStr(), StrEq(""));
  EXPECT_THAT(out, StrEq(""));
  // This error seems to stem from incorrectly handling `--` in the LLD command
  // line. See above; this should go away when the underlying bugs are fixed.
  EXPECT_THAT(err,
              HasSubstr("error: completed parsing all 1 configured positional "
                        "arguments, but found a subsequent `--`"));
}

TEST_F(DriverTest, ConfigJson) {
  EXPECT_TRUE(driver_.RunCommand({"config", "--json"}).success);
  EXPECT_THAT(test_error_stream_.TakeStr(), StrEq(""));

  // Make sure the output parses as JSON.
  std::string output = test_output_stream_.TakeStr();
  llvm::Expected<llvm::json::Value> json_value = llvm::json::parse(output);
  if (auto error = json_value.takeError()) {
    FAIL() << "Unable to parse to JSON: " << toString(std::move(error))
           << "\nOriginal text:\n"
           << output << "\n";
  }
  llvm::json::Object* json_obj = json_value->getAsObject();
  ASSERT_THAT(json_obj, NotNull());

  // Check relevant paths in the output point to existing directories.
  std::optional<llvm::StringRef> install_root =
      json_obj->getString("INSTALL_ROOT");
  ASSERT_THAT(install_root, Ne(std::nullopt));
  EXPECT_THAT(Filesystem::Cwd().OpenDir(install_root->str()), IsSuccess(_));