Files
carbon-lang/explorer/file_test.cpp
T
Prabhat SachdevaandRichard Smith 04d9a7b533 Improved trace output selection using program phase filtering (#2851)
By implementing these improvements, users will have the ability to choose specific parts of the trace output.

Currently, when executing a file using the explorer with the --trace_file=- or --trace_file=filename.txt flag, the resulting output is an extensive and verbose log containing all the information.

In this PR, I have introduced the `ProgramPhase` enum class, which have distinct phases encountered during the compilation of a program in the explorer. Each member of this enum class corresponds to a specific phase, signifying the relevant information to be included in the trace output.

The phases covered by the `ProgramPhase` enum class are as follows:

1. Printing the source program
2. Name resolution
3. Control flow resolution
4. Type checking
5. Unformed variable resolution
6. Printing declarations
7. Printing the timings
8. Printing whole output.

These phases can be selected by passing the following compiler flags along with `--trace_file=-`.
`-trace_source_program`, `-trace_name_resolution`, `-trace_control_flow_resolution`, `-trace_type_checking`, `-trace_unformed_variables_resolution`, `-trace_declarations`, `-trace_execution`, `-trace_timing` and `-trace_all`. If none of these flags is passed only execution trace will be added to the output.

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2023-06-08 10:49:13 -07:00

99 lines
3.3 KiB
C++

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "explorer/parse_and_execute/parse_and_execute.h"
#include "testing/file_test/file_test_base.h"
namespace Carbon::Testing {
namespace {
class ParseAndExecuteTestFile : public FileTestBase {
public:
explicit ParseAndExecuteTestFile(const std::filesystem::path& path,
bool trace)
: FileTestBase(path), trace_(trace) {}
auto SetUp() -> void override {
if (trace_) {
std::string path_str = path().string();
llvm::StringRef path_ref = path_str;
if (path_ref.find("/limits/") != llvm::StringRef::npos) {
GTEST_SKIP()
<< "`limits` tests check for various limit conditions (such as an "
"infinite loop). The tests collectively don't test tracing "
"because it creates substantial additional overhead.";
} else if (path_ref.endswith(
"testdata/assoc_const/rewrite_large_type.carbon") ||
path_ref.endswith(
"testdata/linked_list/typed_linked_list.carbon")) {
GTEST_SKIP() << "Expensive test to trace";
}
}
}
auto RunWithFiles(const llvm::SmallVector<std::string>& test_files,
llvm::raw_ostream& stdout, llvm::raw_ostream& stderr)
-> bool override {
if (test_files.size() != 1) {
ADD_FAILURE() << "Only 1 file is supported: " << test_files.size()
<< " provided";
return false;
}
// Capture trace streaming, but only when in debug mode.
TraceStream trace_stream;
std::string trace_stream_str;
llvm::raw_string_ostream trace_stream_ostream(trace_stream_str);
if (trace_) {
trace_stream.set_stream(&trace_stream_ostream);
trace_stream.set_allowed_phases({ProgramPhase::All});
}
// Set the location of the prelude.
char* test_srcdir = getenv("TEST_SRCDIR");
CARBON_CHECK(test_srcdir != nullptr);
std::string prelude_path(test_srcdir);
prelude_path += "/carbon/explorer/data/prelude.carbon";
// Run the parse. Parser debug output is always off because it's difficult
// to redirect.
auto result =
ParseAndExecuteFile(prelude_path, path().filename().string(),
/*parser_debug=*/false, &trace_stream, &stdout);
// This mirrors printing currently done by main.cpp.
if (result.ok()) {
stdout << "result: " << *result << "\n";
} else {
stderr << result.error() << "\n";
}
if (trace_) {
EXPECT_FALSE(trace_stream_str.empty())
<< "Tracing should always do something";
}
return result.ok();
}
private:
bool trace_;
};
} // namespace
extern auto RegisterFileTests(
const llvm::SmallVector<std::filesystem::path>& paths) -> void {
ParseAndExecuteTestFile::RegisterTests(
"ParseAndExecuteTestFile", paths, [=](const std::filesystem::path& path) {
return new ParseAndExecuteTestFile(path, /*trace=*/false);
});
ParseAndExecuteTestFile::RegisterTests(
"ParseAndExecuteTestFile.trace", paths,
[=](const std::filesystem::path& path) {
return new ParseAndExecuteTestFile(path, /*trace=*/true);
});
}
} // namespace Carbon::Testing