1919// conformance tests; as well as integrating better with C++ testing
2020// infrastructure.
2121
22+ #include < cstdint>
2223#include < cstdlib>
2324#include < fstream>
2425#include < ios>
3233#include " cel/expr/eval.pb.h"
3334#include " google/api/expr/v1alpha1/checked.pb.h" // IWYU pragma: keep
3435#include " google/api/expr/v1alpha1/eval.pb.h"
36+ #include " google/api/expr/v1alpha1/syntax.pb.h" // IWYU pragma: keep
3537#include " google/api/expr/v1alpha1/value.pb.h"
3638#include " cel/expr/value.pb.h"
3739#include " google/rpc/code.pb.h"
@@ -126,6 +128,43 @@ MATCHER_P(MatchesConformanceValue, expected, "") {
126128 return false ;
127129}
128130
131+ MATCHER_P (ResultTypeMatches, expected, " " ) {
132+ static auto * kDifferencer = []() {
133+ auto * differencer = new MessageDifferencer ();
134+ differencer->set_message_field_comparison (MessageDifferencer::EQUIVALENT);
135+ return differencer;
136+ }();
137+
138+ const cel::expr::Type& want = expected;
139+ const google::api::expr::v1alpha1::CheckedExpr& checked_expr = arg;
140+
141+ int64_t root_id = checked_expr.expr ().id ();
142+ auto it = checked_expr.type_map ().find (root_id);
143+
144+ if (it == checked_expr.type_map ().end ()) {
145+ (*result_listener) << " type map does not contain root id: " << root_id;
146+ return false ;
147+ }
148+
149+ auto got_versioned = it->second ;
150+ std::string serialized;
151+ cel::expr::Type got;
152+ if (!got_versioned.SerializeToString (&serialized) ||
153+ !got.ParseFromString (serialized)) {
154+ (*result_listener) << " type cannot be converted from versioned type: "
155+ << DescribeMessage (got_versioned);
156+ return false ;
157+ }
158+
159+ if (kDifferencer ->Compare (got, want)) {
160+ return true ;
161+ }
162+ (*result_listener) << " got: " << DescribeMessage (got);
163+ (*result_listener) << " \n " ;
164+ (*result_listener) << " wanted: " << DescribeMessage (want);
165+ return false ;
166+ }
167+
129168bool ShouldSkipTest (absl::Span<const std::string> tests_to_skip,
130169 absl::string_view name) {
131170 for (absl::string_view test_to_skip : tests_to_skip) {
@@ -202,6 +241,14 @@ class ConformanceTest : public testing::Test {
202241 check_response.release_checked_expr ());
203242 }
204243
244+ if (test_.check_only ()) {
245+ ASSERT_TRUE (test_.has_typed_result ())
246+ << " test must specify a typed result if check_only is set" ;
247+ EXPECT_THAT (eval_request.checked_expr (),
248+ ResultTypeMatches (test_.typed_result ().deduced_type ()));
249+ return ;
250+ }
251+
205252 EvalResponse eval_response;
206253 if (auto status = service_->Eval (eval_request, eval_response);
207254 !status.ok ()) {
@@ -219,6 +266,19 @@ class ConformanceTest : public testing::Test {
219266 EXPECT_THAT (test_value, MatchesConformanceValue (test_.value ()));
220267 break ;
221268 }
269+ case SimpleTest::kTypedResult : {
270+ ASSERT_TRUE (eval_request.has_checked_expr ())
271+ << " expression was not type checked" ;
272+ absl::Cord serialized;
273+ ABSL_CHECK (eval_response.result ().SerializePartialToCord (&serialized));
274+ cel::expr::ExprValue test_value;
275+ ABSL_CHECK (test_value.ParsePartialFromCord (serialized));
276+ EXPECT_THAT (test_value,
277+ MatchesConformanceValue (test_.typed_result ().result ()));
278+ EXPECT_THAT (eval_request.checked_expr (),
279+ ResultTypeMatches (test_.typed_result ().deduced_type ()));
280+ break ;
281+ }
222282 case SimpleTest::kEvalError :
223283 EXPECT_TRUE (eval_response.result ().has_error ())
224284 << eval_response.result ();
0 commit comments