Skip to content

Commit febb866

Browse files
jnthntatumcopybara-github
authored andcommitted
Consistency fixes for legacy adapter types:
- make direct CelMap::Get calls return error as the legacy implementations did - avoid copying messages already marked as unsafe when converting to legacy PiperOrigin-RevId: 972686690
1 parent 11dba5a commit febb866

8 files changed

Lines changed: 79 additions & 30 deletions

File tree

common/legacy_value.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,11 @@ CelValue LegacyTrivialStructValue(google::protobuf::Arena* absl_nonnull arena,
260260
}
261261
if (auto parsed_message_value = value.AsParsedMessage();
262262
parsed_message_value) {
263+
if (interop_internal::IsUnsafeParsedMessageValue(*parsed_message_value)) {
264+
return CelValue::CreateMessageWrapper(
265+
AsMessageWrapper(cel::to_address(*parsed_message_value),
266+
&GetGenericProtoTypeInfoInstance()));
267+
}
263268
auto maybe_cloned = parsed_message_value->Clone(arena);
264269
return CelValue::CreateMessageWrapper(MessageWrapper(
265270
cel::to_address(maybe_cloned), &GetGenericProtoTypeInfoInstance()));

common/legacy_value.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ class MessageFactory;
6565

6666
namespace cel::interop_internal {
6767

68+
inline bool IsUnsafeParsedMessageValue(const cel::ParsedMessageValue& value) {
69+
return value.is_unsafe();
70+
}
71+
6872
// Returns the underlying `google::protobuf::Message` of a `cel::Value` if it is a legacy
6973
// message with the default type info, or `nullptr` otherwise.
7074
const google::protobuf::Message* absl_nullable GetLegacyMessage(const Value& value);

common/values/legacy_map_value.cc

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include <utility>
2323

2424
#include "absl/base/nullability.h"
25-
#include "absl/base/optimization.h"
2625
#include "absl/log/absl_check.h"
2726
#include "absl/status/status.h"
2827
#include "absl/strings/str_cat.h"
@@ -218,21 +217,33 @@ class LegacyParsedMapFieldMapValue final
218217
if (arena == nullptr) {
219218
arena = arena_;
220219
}
221-
if (auto status =
222-
google::api::expr::runtime::CelValue::CheckMapKeyType(key);
223-
!status.ok()) {
224-
status.IgnoreError();
225-
return std::nullopt;
226-
}
227220
Value modern_key;
228-
if (ABSL_PREDICT_FALSE(!ModernValue(arena, key, modern_key).ok())) {
221+
if (!ModernValue(arena, key, modern_key).ok()) {
222+
// Legacy to modern should succeed for a valid CelValue.
229223
return std::nullopt;
230224
}
231225
Value modern_val;
232-
auto status_or_found =
233-
Find(modern_key, google::protobuf::DescriptorPool::generated_pool(),
234-
google::protobuf::MessageFactory::generated_factory(), arena, &modern_val);
235-
if (!status_or_found.ok() || !*status_or_found) {
226+
// Call custom map Find directly. MapValue normally handles wrapping
227+
// non-ok result to error value types, so emulate that here.
228+
//
229+
// Use the descriptor pool and message factory from the value. This is not
230+
// totally consistent with modern APIs, but this should behave the same as
231+
// the legacy map did.
232+
const google::protobuf::Message* msg = value_.message_;
233+
ABSL_DCHECK(msg->GetDescriptor() != nullptr);
234+
ABSL_DCHECK(msg->GetReflection() != nullptr);
235+
236+
const google::protobuf::DescriptorPool* descriptor_pool =
237+
msg->GetDescriptor()->file()->pool();
238+
google::protobuf::MessageFactory* message_factory =
239+
msg->GetReflection()->GetMessageFactory();
240+
auto found =
241+
Find(modern_key, descriptor_pool, message_factory, arena, &modern_val);
242+
if (!found.ok()) {
243+
return google::api::expr::runtime::CreateErrorValue(arena,
244+
found.status());
245+
}
246+
if (!(*found) && !modern_val.IsError()) {
236247
return std::nullopt;
237248
}
238249
return UnsafeLegacyValue(modern_val, /*stable=*/false, arena);
@@ -401,21 +412,25 @@ class LegacyParsedJsonMapValue final
401412
if (arena == nullptr) {
402413
arena = arena_;
403414
}
404-
if (auto status =
405-
google::api::expr::runtime::CelValue::CheckMapKeyType(key);
406-
!status.ok()) {
407-
status.IgnoreError();
408-
return std::nullopt;
409-
}
410415
Value modern_key;
411-
if (ABSL_PREDICT_FALSE(!ModernValue(arena, key, modern_key).ok())) {
416+
if (!ModernValue(arena, key, modern_key).ok()) {
417+
// Legacy to modern should succeed for a valid CelValue.
412418
return std::nullopt;
413419
}
414420
Value modern_val;
415-
auto status_or_found = value_.Find(
416-
modern_key, google::protobuf::DescriptorPool::generated_pool(),
417-
google::protobuf::MessageFactory::generated_factory(), arena, &modern_val);
418-
if (!status_or_found.ok() || !*status_or_found) {
421+
// Call custom map Find directly. MapValue normally handles wrapping
422+
// non-ok result to error value types, so emulate that here.
423+
//
424+
// We know that the descriptor pool and message factory aren't needed here,
425+
// so fine to use generated.
426+
auto found =
427+
Find(modern_key, google::protobuf::DescriptorPool::generated_pool(),
428+
google::protobuf::MessageFactory::generated_factory(), arena, &modern_val);
429+
if (!found.ok()) {
430+
return google::api::expr::runtime::CreateErrorValue(arena,
431+
found.status());
432+
}
433+
if (!(*found) && !modern_val.IsError()) {
419434
return std::nullopt;
420435
}
421436
return UnsafeLegacyValue(modern_val, /*stable=*/false, arena);

common/values/legacy_struct_value_test.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,18 @@ TEST_F(LegacyStructValueTest, MapFieldKeyTypeValidation) {
190190
CelValue str_key = CelValue::CreateString(&str_key_val);
191191
auto invalid_has_res = cel_map->Has(str_key);
192192
EXPECT_THAT(invalid_has_res, StatusIs(absl::StatusCode::kInvalidArgument));
193+
194+
auto invalid_get_res = cel_map->Get(arena(), str_key);
195+
ASSERT_TRUE(invalid_get_res.has_value());
196+
ASSERT_TRUE(invalid_get_res->IsError());
197+
EXPECT_THAT(*invalid_get_res->ErrorOrDie(),
198+
StatusIs(absl::StatusCode::kInvalidArgument));
199+
200+
auto invalid_subscript_res = (*cel_map)[str_key];
201+
ASSERT_TRUE(invalid_subscript_res.has_value());
202+
ASSERT_TRUE(invalid_subscript_res->IsError());
203+
EXPECT_THAT(*invalid_subscript_res->ErrorOrDie(),
204+
StatusIs(absl::StatusCode::kInvalidArgument));
193205
}
194206

195207
TEST_F(LegacyStructValueTest, JsonStructAccess) {

common/values/parsed_map_field_value.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ class ValueIterator;
4747
class ListValue;
4848
class ParsedJsonMapValue;
4949

50+
namespace common_internal {
51+
class LegacyParsedMapFieldMapValue;
52+
} // namespace common_internal
53+
5054
// ParsedMapFieldValue is a MapValue over a map field of a parsed protocol
5155
// buffer message.
5256
class ParsedMapFieldValue final
@@ -192,6 +196,7 @@ class ParsedMapFieldValue final
192196
friend class ParsedJsonMapValue;
193197
friend class common_internal::ValueMixin<ParsedMapFieldValue>;
194198
friend class common_internal::MapValueMixin<ParsedMapFieldValue>;
199+
friend class common_internal::LegacyParsedMapFieldMapValue;
195200
friend ParsedMapFieldValue UnsafeParsedMapFieldValue(
196201
const google::protobuf::Message* absl_nonnull message,
197202
const google::protobuf::FieldDescriptor* absl_nonnull field);

common/values/parsed_message_value.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@
4848

4949
namespace cel {
5050

51+
namespace interop_internal {
52+
bool IsUnsafeParsedMessageValue(const ParsedMessageValue& value);
53+
}
54+
5155
class MessageValue;
5256
class StructValue;
5357
class Value;
@@ -189,6 +193,8 @@ class ParsedMessageValue final
189193
friend class common_internal::StructValueMixin<ParsedMessageValue>;
190194
friend ParsedMessageValue UnsafeParsedMessageValue(
191195
const google::protobuf::Message* absl_nonnull value);
196+
friend bool interop_internal::IsUnsafeParsedMessageValue(
197+
const ParsedMessageValue& value);
192198

193199
explicit ParsedMessageValue(
194200
const google::protobuf::Message* absl_nonnull value ABSL_ATTRIBUTE_LIFETIME_BOUND)

eval/internal/BUILD

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,10 @@ cc_test(
5656
"//eval/public/structs:trivial_legacy_type_info",
5757
"//eval/testutil:test_message_cc_proto",
5858
"//internal:testing",
59-
"@com_google_absl//absl/status:statusor",
59+
"@com_google_absl//absl/log:absl_check",
6060
"@com_google_absl//absl/strings",
6161
"@com_google_absl//absl/time",
6262
"@com_google_absl//absl/types:span",
63-
"@com_google_absl//absl/types:variant",
6463
"@com_google_googleapis//google/rpc/context:attribute_context_cc_proto",
6564
"@com_google_protobuf//:any_cc_proto",
6665
"@com_google_protobuf//:protobuf",

eval/internal/cel_value_equal_test.cc

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,21 @@
1818
#include <cstdint>
1919
#include <limits>
2020
#include <memory>
21+
#include <optional>
2122
#include <string>
2223
#include <tuple>
2324
#include <utility>
25+
#include <variant>
2426
#include <vector>
2527

2628
#include "google/protobuf/any.pb.h"
2729
#include "google/rpc/context/attribute_context.pb.h"
2830
#include "google/protobuf/descriptor.pb.h"
29-
#include "absl/status/statusor.h"
31+
#include "absl/log/absl_check.h"
3032
#include "absl/strings/str_cat.h"
3133
#include "absl/strings/string_view.h"
3234
#include "absl/time/time.h"
3335
#include "absl/types/span.h"
34-
#include "absl/types/variant.h"
3536
#include "eval/public/cel_value.h"
3637
#include "eval/public/containers/container_backed_list_impl.h"
3738
#include "eval/public/containers/container_backed_map_impl.h"
@@ -131,6 +132,8 @@ const std::vector<CelValue>& ValueExamples1() {
131132
result->push_back(CelValue::CreateMap(&CelMapExample1()));
132133
result->push_back(CelValue::CreateCelTypeView("type"));
133134

135+
ABSL_CHECK_EQ(arena.SpaceUsed(), 0) << "Arena should not be used.";
136+
134137
return result.release();
135138
}();
136139
return *examples;
@@ -185,7 +188,7 @@ std::string CelValueEqualTestName(
185188
}
186189

187190
TEST_P(CelValueEqualImplTypesTest, Basic) {
188-
absl::optional<bool> result = CelValueEqualImpl(lhs(), rhs());
191+
std::optional<bool> result = CelValueEqualImpl(lhs(), rhs());
189192

190193
if (lhs().IsNull() || rhs().IsNull()) {
191194
if (lhs().IsNull() && rhs().IsNull()) {
@@ -267,7 +270,7 @@ const std::vector<NumericInequalityTestCase>& NumericValuesNotEqualExample() {
267270
using NumericInequalityTest = testing::TestWithParam<NumericInequalityTestCase>;
268271
TEST_P(NumericInequalityTest, NumericValues) {
269272
NumericInequalityTestCase test_case = GetParam();
270-
absl::optional<bool> result = CelValueEqualImpl(test_case.a, test_case.b);
273+
std::optional<bool> result = CelValueEqualImpl(test_case.a, test_case.b);
271274
EXPECT_TRUE(result.has_value());
272275
EXPECT_EQ(*result, false);
273276
}
@@ -280,7 +283,7 @@ INSTANTIATE_TEST_SUITE_P(
280283
});
281284

282285
TEST(CelValueEqualImplTest, LossyNumericEquality) {
283-
absl::optional<bool> result = CelValueEqualImpl(
286+
std::optional<bool> result = CelValueEqualImpl(
284287
CelValue::CreateDouble(
285288
static_cast<double>(std::numeric_limits<int64_t>::max()) - 1),
286289
CelValue::CreateInt64(std::numeric_limits<int64_t>::max()));

0 commit comments

Comments
 (0)