Skip to content

Commit 16a71c5

Browse files
jnthntatumcopybara-github
authored andcommitted
Add support for type checker type deduction conformance tests.
PiperOrigin-RevId: 703160475
1 parent 26c810a commit 16a71c5

File tree

3 files changed

+67
-6
lines changed

3 files changed

+67
-6
lines changed

bazel/deps.bzl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,10 @@ def cel_spec_deps():
142142
url = "https://github.com/bazelbuild/rules_python/releases/download/0.33.2/rules_python-0.33.2.tar.gz",
143143
)
144144

145-
CEL_SPEC_GIT_SHA = "373994d7e20e582fce56767b01ac5039524cddab" # Oct 23, 2024
145+
CEL_SPEC_GIT_SHA = "afa18f9bd5a83f5960ca06c1f9faea406ab34ccc" # Dec 2, 2024
146146
http_archive(
147147
name = "com_google_cel_spec",
148-
sha256 = "b498a768140fc0ed0314eef8b2519a48287661d09ca15b17c8ca34088af6aac3",
148+
sha256 = "19b4084ba33cc8da7a640d999e46731efbec585ad2995951dc61a7af24f059cb",
149149
strip_prefix = "cel-spec-" + CEL_SPEC_GIT_SHA,
150150
urls = ["https://github.com/google/cel-spec/archive/" + CEL_SPEC_GIT_SHA + ".zip"],
151151
)

conformance/BUILD

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ _ALL_TESTS = [
167167
"@com_google_cel_spec//tests/simple:testdata/unknowns.textproto",
168168
"@com_google_cel_spec//tests/simple:testdata/wrappers.textproto",
169169
"@com_google_cel_spec//tests/simple:testdata/block_ext.textproto",
170+
"@com_google_cel_spec//tests/simple:testdata/type_deduction.textproto",
170171
]
171172

172173
_TESTS_TO_SKIP_MODERN = [
@@ -301,14 +302,14 @@ gen_conformance_tests(
301302
name = "conformance_parse_only",
302303
data = _ALL_TESTS,
303304
modern = True,
304-
skip_tests = _TESTS_TO_SKIP_MODERN,
305+
skip_tests = _TESTS_TO_SKIP_MODERN + ["type_deductions"],
305306
)
306307

307308
gen_conformance_tests(
308309
name = "conformance_legacy_parse_only",
309310
data = _ALL_TESTS,
310311
modern = False,
311-
skip_tests = _TESTS_TO_SKIP_LEGACY,
312+
skip_tests = _TESTS_TO_SKIP_LEGACY + ["type_deductions"],
312313
)
313314

314315
gen_conformance_tests(
@@ -330,7 +331,7 @@ gen_conformance_tests(
330331
dashboard = True,
331332
data = _ALL_TESTS,
332333
modern = True,
333-
skip_tests = _TESTS_TO_SKIP_MODERN_DASHBOARD,
334+
skip_tests = _TESTS_TO_SKIP_MODERN_DASHBOARD + ["type_deductions"],
334335
tags = [
335336
"guitar",
336337
"notap",
@@ -355,7 +356,7 @@ gen_conformance_tests(
355356
dashboard = True,
356357
data = _ALL_TESTS,
357358
modern = False,
358-
skip_tests = _TESTS_TO_SKIP_LEGACY_DASHBOARD,
359+
skip_tests = _TESTS_TO_SKIP_LEGACY_DASHBOARD + ["type_deductions"],
359360
tags = [
360361
"guitar",
361362
"notap",

conformance/run.cc

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
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>
@@ -32,6 +33,7 @@
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+
129168
bool 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

Comments
 (0)