Skip to content

Commit 06d912e

Browse files
jnthntatumcopybara-github
authored andcommitted
Add helper for parsing a single test case from yaml.
PiperOrigin-RevId: 978544043
1 parent 680d282 commit 06d912e

3 files changed

Lines changed: 86 additions & 29 deletions

File tree

policy/BUILD

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,6 @@ cc_test(
225225

226226
cc_library(
227227
name = "test_util",
228-
testonly = True,
229228
srcs = ["test_util.cc"],
230229
hdrs = ["test_util.h"],
231230
copts = ["-fexceptions"],

policy/test_util.cc

Lines changed: 81 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
#include "policy/test_util.h"
1111

1212
#include <cstdint>
13+
#include <exception>
1314
#include <string>
1415
#include <utility>
15-
#include <vector>
1616

1717
#include "cel/expr/eval.pb.h"
1818
#include "cel/expr/value.pb.h"
@@ -131,6 +131,73 @@ absl::Status ParseTestOutput(const YAML::Node& node,
131131
return YamlToExprValue(node, output->mutable_result_value());
132132
}
133133

134+
absl::Status ParseTestCaseNode(
135+
const YAML::Node& test_node,
136+
cel::expr::conformance::test::TestCase* test_case) {
137+
if (test_node.IsNull()) {
138+
return absl::OkStatus();
139+
}
140+
if (!test_node.IsMap()) {
141+
return absl::InvalidArgumentError("Test case must be a YAML mapping");
142+
}
143+
if (test_node["name"].IsDefined()) {
144+
test_case->set_name(test_node["name"].as<std::string>());
145+
}
146+
if (test_node["description"].IsDefined()) {
147+
test_case->set_description(test_node["description"].as<std::string>());
148+
}
149+
if (test_node["expr"].IsDefined()) {
150+
test_case->set_expr(test_node["expr"].as<std::string>());
151+
}
152+
if (test_node["context_expr"].IsDefined()) {
153+
test_case->mutable_input_context()->set_context_expr(
154+
test_node["context_expr"].as<std::string>());
155+
} else if (test_node["input_context"].IsDefined() &&
156+
test_node["input_context"].IsMap() &&
157+
test_node["input_context"]["context_expr"].IsDefined()) {
158+
test_case->mutable_input_context()->set_context_expr(
159+
test_node["input_context"]["context_expr"].as<std::string>());
160+
}
161+
if (test_node["disable_check"].IsDefined()) {
162+
test_case->set_disable_check(test_node["disable_check"].as<bool>());
163+
}
164+
165+
YAML::Node input_node = test_node["input"];
166+
if (input_node.IsDefined() && input_node.IsMap()) {
167+
auto* input_map = test_case->mutable_input();
168+
for (auto it = input_node.begin(); it != input_node.end(); ++it) {
169+
std::string var_name = it->first.as<std::string>();
170+
cel::expr::conformance::test::InputValue input_val;
171+
CEL_RETURN_IF_ERROR(ParseInputValue(it->second, &input_val));
172+
(*input_map)[var_name] = std::move(input_val);
173+
}
174+
}
175+
176+
YAML::Node output_node = test_node["output"];
177+
if (output_node.IsDefined()) {
178+
CEL_RETURN_IF_ERROR(
179+
ParseTestOutput(output_node, test_case->mutable_output()));
180+
}
181+
return absl::OkStatus();
182+
}
183+
184+
absl::StatusOr<cel::expr::conformance::test::TestCase> ParseTestCaseYamlImpl(
185+
absl::string_view yaml_content) {
186+
if (yaml_content.empty()) {
187+
return cel::expr::conformance::test::TestCase();
188+
}
189+
YAML::Node test_node;
190+
try {
191+
test_node = YAML::Load(std::string(yaml_content));
192+
} catch (const std::exception& e) {
193+
return absl::InvalidArgumentError(
194+
absl::StrCat("Failed to parse YAML: ", e.what()));
195+
}
196+
cel::expr::conformance::test::TestCase test_case;
197+
CEL_RETURN_IF_ERROR(ParseTestCaseNode(test_node, &test_case));
198+
return test_case;
199+
}
200+
134201
absl::StatusOr<cel::expr::conformance::test::TestSuite>
135202
ParsePolicyTestSuiteYamlImpl(absl::string_view yaml_content) {
136203
YAML::Node tests_node;
@@ -174,33 +241,7 @@ ParsePolicyTestSuiteYamlImpl(absl::string_view yaml_content) {
174241

175242
for (const auto& test_node : tests) {
176243
auto* test_case = section->add_tests();
177-
if (test_node["name"].IsDefined()) {
178-
test_case->set_name(test_node["name"].as<std::string>());
179-
}
180-
if (test_node["description"].IsDefined()) {
181-
test_case->set_description(test_node["description"].as<std::string>());
182-
}
183-
if (test_node["context_expr"].IsDefined()) {
184-
test_case->mutable_input_context()->set_context_expr(
185-
test_node["context_expr"].as<std::string>());
186-
}
187-
188-
YAML::Node input_node = test_node["input"];
189-
if (input_node.IsDefined() && input_node.IsMap()) {
190-
auto* input_map = test_case->mutable_input();
191-
for (auto it = input_node.begin(); it != input_node.end(); ++it) {
192-
std::string var_name = it->first.as<std::string>();
193-
cel::expr::conformance::test::InputValue input_val;
194-
CEL_RETURN_IF_ERROR(ParseInputValue(it->second, &input_val));
195-
(*input_map)[var_name] = std::move(input_val);
196-
}
197-
}
198-
199-
YAML::Node output_node = test_node["output"];
200-
if (output_node.IsDefined()) {
201-
CEL_RETURN_IF_ERROR(
202-
ParseTestOutput(output_node, test_case->mutable_output()));
203-
}
244+
CEL_RETURN_IF_ERROR(ParseTestCaseNode(test_node, test_case));
204245
}
205246
}
206247

@@ -218,4 +259,16 @@ ParsePolicyTestSuiteYaml(absl::string_view yaml_content) {
218259
}
219260
}
220261

262+
absl::StatusOr<cel::expr::conformance::test::TestCase> ParseTestCaseYaml(
263+
absl::string_view yaml_content) {
264+
try {
265+
return ParseTestCaseYamlImpl(yaml_content);
266+
} catch (const std::exception& e) {
267+
return absl::InvalidArgumentError(
268+
absl::StrCat("Failed to parse YAML: ", e.what()));
269+
} catch (...) {
270+
return absl::InvalidArgumentError("Failed to parse YAML");
271+
}
272+
}
273+
221274
} // namespace cel::test

policy/test_util.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ namespace cel::test {
2828
absl::StatusOr<cel::expr::conformance::test::TestSuite>
2929
ParsePolicyTestSuiteYaml(absl::string_view yaml_content);
3030

31+
// Parses a YAML string representing an individual test case and adapts it to
32+
// the cel.expr.conformance.test.TestCase protobuf message.
33+
absl::StatusOr<cel::expr::conformance::test::TestCase> ParseTestCaseYaml(
34+
absl::string_view yaml_content);
35+
3136
} // namespace cel::test
3237

3338
#endif // THIRD_PARTY_CEL_CPP_POLICY_TEST_UTIL_H_

0 commit comments

Comments
 (0)