Make the file_test binary work without custom environment variables. (#5442)

Instead of crashing when run outside of `bazel`, make the toolchain's
`file_test` binary work properly when no test-specific environment
variables are set. This makes it a lot easier to run `file_test` under a
debugger.

There are two main changes here:

- Don't crash if `$TEST_TMPDIR` is unset. Instead, fall back to LLVM's
temporary directory (typically `$TMPDIR`). We already did this in some
places in tests. We now do it in more places.
- Don't fall back to a target label of `<target>` in the reproduction
commands if `$TEST_TARGET` is unset, because this causes all the tests
to fail because their output doesn't match the expected output due to a
differing bazel run command. Instead explicitly specify the target from
the `FileTestBase`-derived class.

Infrastructure for this has been added generally, but only rolled out to
the toolchain `file_test` binary for now.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
This commit is contained in:
Richard Smith
2025-05-07 22:28:13 +00:00
committed by GitHub
co-authored by Jon Ross-Perkins
parent f2a16d8742
commit 66caff2c26
9 changed files with 61 additions and 40 deletions
+17 -20
View File
@@ -78,7 +78,7 @@ struct FileTestInfo {
std::string test_name;
// A factory function for creating the test object.
std::function<auto()->FileTestBase*> factory_fn;
std::function<auto()->std::unique_ptr<FileTestBase>> factory_fn;
// gtest's information about the test.
::testing::TestInfo* registered_test;
@@ -134,21 +134,11 @@ static auto CompareFailPrefix(llvm::StringRef filename, bool success) -> void {
}
}
// Modes for GetBazelCommand.
enum class BazelMode : uint8_t {
Autoupdate,
Dump,
Test,
};
// Returns the requested bazel command string for the given execution mode.
static auto GetBazelCommand(BazelMode mode, llvm::StringRef test_name)
-> std::string {
auto FileTestBase::GetBazelCommand(BazelMode mode) -> std::string {
RawStringOstream args;
const char* target = getenv("TEST_TARGET");
args << "bazel " << ((mode == BazelMode::Test) ? "test" : "run") << " "
<< (target ? target : "<target>") << " ";
<< GetBazelLabel() << " ";
switch (mode) {
case BazelMode::Autoupdate:
@@ -165,10 +155,15 @@ static auto GetBazelCommand(BazelMode mode, llvm::StringRef test_name)
}
args << "--file_tests=";
args << test_name;
args << test_name();
return args.TakeStr();
}
auto FileTestBase::GetBazelLabel() -> std::string {
const char* target = getenv("TEST_TARGET");
return target ? target : "<target>";
}
// Runs the FileTestAutoupdater, returning the result.
static auto RunAutoupdater(FileTestBase* test_base, const TestFile& test_file,
bool dry_run) -> bool {
@@ -193,8 +188,8 @@ static auto RunAutoupdater(FileTestBase* test_base, const TestFile& test_file,
return FileTestAutoupdater(
std::filesystem::absolute(test_base->test_name().str()),
GetBazelCommand(BazelMode::Test, test_base->test_name()),
GetBazelCommand(BazelMode::Dump, test_base->test_name()),
test_base->GetBazelCommand(FileTestBase::BazelMode::Test),
test_base->GetBazelCommand(FileTestBase::BazelMode::Dump),
test_file.input_content, filenames,
*test_file.autoupdate_line_number, test_file.autoupdate_split,
test_file.non_check_lines, test_file.actual_stdout,
@@ -268,7 +263,8 @@ auto FileTestCase::TestBody() -> void {
if (HasFailure()) {
llvm::errs() << "\nTo test this file alone, run:\n "
<< GetBazelCommand(BazelMode::Test, test_info_->test_name)
<< test_info_->factory_fn()->GetBazelCommand(
FileTestBase::BazelMode::Test)
<< "\n\n";
if (!test_file.autoupdate_line_number) {
llvm::errs() << "\nThis test is NOAUTOUPDATE.\n\n";
@@ -276,8 +272,8 @@ auto FileTestCase::TestBody() -> void {
}
if (test_info_->autoupdate_differs) {
ADD_FAILURE() << "Autoupdate would make changes to the file content. Run:\n"
<< GetBazelCommand(BazelMode::Autoupdate,
test_info_->test_name);
<< test_info_->factory_fn()->GetBazelCommand(
FileTestBase::BazelMode::Autoupdate);
}
}
@@ -372,7 +368,8 @@ static auto RunSingleTestHelper(FileTestInfo& test, FileTestBase& test_instance)
-> void {
Timer timer;
// Add a crash trace entry with the single-file test command.
std::string test_command = GetBazelCommand(BazelMode::Test, test.test_name);
std::string test_command =
test_instance.GetBazelCommand(FileTestBase::BazelMode::Test);
llvm::PrettyStackTraceString stack_trace_entry(test_command.c_str());
if (auto err = RunTestFile(test_instance, absl::GetFlag(FLAGS_dump_output),