Skip to content

Commit 2ed8960

Browse files
CEL Dev Teamcopybara-github
authored andcommitted
Internal Changes
PiperOrigin-RevId: 813597086
1 parent 4010d6e commit 2ed8960

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

testing/testrunner/runner_bin.cc

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414

1515
// This binary is a test runner for CEL tests. It is used to run CEL tests
1616
// written in the CEL test suite format.
17+
#include <cerrno>
18+
#include <cstdlib>
19+
#include <cstring>
1720
#include <fstream>
1821
#include <functional>
1922
#include <ios>
@@ -31,6 +34,7 @@
3134
#include "absl/strings/str_cat.h"
3235
#include "absl/strings/str_format.h"
3336
#include "absl/strings/str_join.h"
37+
#include "absl/strings/string_view.h"
3438
#include "eval/public/cel_expression.h"
3539
#include "internal/testing.h"
3640
#include "runtime/runtime.h"
@@ -110,9 +114,56 @@ class CoverageReportingEnvironment : public testing::Environment {
110114
<< absl::StrJoin(coverage_report.unencountered_branches,
111115
"\n");
112116
}
117+
118+
if (!coverage_report.dot_graph.empty()) {
119+
WriteDotGraphToArtifact(coverage_report.dot_graph);
120+
}
113121
}
114122

115123
private:
124+
void WriteDotGraphToArtifact(absl::string_view dot_graph) {
125+
// Save DOT graph to file in TEST_UNDECLARED_OUTPUTS_DIR or default dir
126+
const char* outputs_dir_env = std::getenv("TEST_UNDECLARED_OUTPUTS_DIR");
127+
128+
// For non-Bazel/Blaze users, we write to a subdirectory under the current
129+
// working directory.
130+
// NOMUTANTS --cel_artifacts is for non-Bazel/Blaze users only so not
131+
// needed to test in our case.
132+
std::string outputs_dir =
133+
(outputs_dir_env == nullptr) ? "cel_artifacts" : outputs_dir_env;
134+
135+
std::string coverage_dir = absl::StrCat(outputs_dir, "/cel_test_coverage");
136+
137+
// Creates the directory to store CEL test coverage artifacts.
138+
// The second argument, `0755`, sets the directory's permissions in octal
139+
// format, which is a standard for file system operations. It grants:
140+
// - Owner: read, write, and execute permissions (7 = 4+2+1).
141+
// - Group: read and execute permissions (5 = 4+1).
142+
// - Others: read and execute permissions (5 = 4+1).
143+
// This gives the owner full control while allowing other users to access
144+
// the generated artifacts.
145+
int mkdir_result = mkdir(coverage_dir.c_str(), 0755);
146+
147+
// If mkdir fails, it sets the global 'errno' variable to an error code
148+
// indicating the reason. We check this code to specifically ignore the
149+
// EEXIST error, which just means the directory already exists (this is not
150+
// a real failure we need to warn about).
151+
if (mkdir_result == 0 || errno == EEXIST) {
152+
std::string graph_path =
153+
absl::StrCat(coverage_dir, "/coverage_graph.txt");
154+
std::ofstream out(graph_path);
155+
if (out.is_open()) {
156+
out << dot_graph;
157+
out.close();
158+
} else {
159+
ABSL_LOG(WARNING) << "Failed to open file for writing: " << graph_path;
160+
}
161+
} else {
162+
ABSL_LOG(WARNING) << "Failed to create directory: " << coverage_dir
163+
<< " (reason: " << strerror(errno) << ")";
164+
}
165+
}
166+
116167
cel::test::CoverageIndex& coverage_index_;
117168
};
118169

0 commit comments

Comments
 (0)