|
12 | 12 | // See the License for the specific language governing permissions and |
13 | 13 | // limitations under the License. |
14 | 14 |
|
| 15 | +#include <limits> |
| 16 | +#include <optional> |
15 | 17 | #include <utility> |
16 | 18 | #include <vector> |
17 | 19 |
|
|
21 | 23 | #include "absl/status/statusor.h" |
22 | 24 | #include "absl/strings/string_view.h" |
23 | 25 | #include "absl/time/time.h" |
24 | | -#include "absl/types/optional.h" |
25 | 26 | #include "common/memory.h" |
26 | 27 | #include "common/type.h" |
27 | 28 | #include "common/value.h" |
@@ -225,6 +226,78 @@ TEST_F(ParsedMapFieldValueTest, Find) { |
225 | 226 | IsOkAndHolds(Eq(std::nullopt))); |
226 | 227 | } |
227 | 228 |
|
| 229 | +TEST_F(ParsedMapFieldValueTest, FindDoubleKeyConversion) { |
| 230 | + // Lookups on integer-keyed maps coerce double keys following CEL's numeric |
| 231 | + // semantics ({1: 'x'}[1.0] resolves to key 1). A double that is out of range, |
| 232 | + // negative for an unsigned key, or non-finite must be reported as absent |
| 233 | + // rather than narrowed to the key type: converting such a double straight to |
| 234 | + // an integer with static_cast is undefined behaviour. |
| 235 | + ParsedMapFieldValue int64_map( |
| 236 | + DynamicParseTextProto<TestAllTypesProto3>(R"pb( |
| 237 | + map_int64_int64 { key: 1 value: 100 } |
| 238 | + )pb"), |
| 239 | + DynamicGetField<TestAllTypesProto3>("map_int64_int64"), arena()); |
| 240 | + EXPECT_THAT(int64_map.Find(DoubleValue(1.0), descriptor_pool(), |
| 241 | + message_factory(), arena()), |
| 242 | + IsOkAndHolds(Optional(IntValueIs(100)))); |
| 243 | + EXPECT_THAT(int64_map.Find(DoubleValue(1e19), descriptor_pool(), |
| 244 | + message_factory(), arena()), |
| 245 | + IsOkAndHolds(Eq(std::nullopt))); |
| 246 | + EXPECT_THAT(int64_map.Find(DoubleValue(-1e19), descriptor_pool(), |
| 247 | + message_factory(), arena()), |
| 248 | + IsOkAndHolds(Eq(std::nullopt))); |
| 249 | + EXPECT_THAT( |
| 250 | + int64_map.Find(DoubleValue(std::numeric_limits<double>::infinity()), |
| 251 | + descriptor_pool(), message_factory(), arena()), |
| 252 | + IsOkAndHolds(Eq(std::nullopt))); |
| 253 | + EXPECT_THAT( |
| 254 | + int64_map.Find(DoubleValue(std::numeric_limits<double>::quiet_NaN()), |
| 255 | + descriptor_pool(), message_factory(), arena()), |
| 256 | + IsOkAndHolds(Eq(std::nullopt))); |
| 257 | + |
| 258 | + ParsedMapFieldValue uint64_map( |
| 259 | + DynamicParseTextProto<TestAllTypesProto3>(R"pb( |
| 260 | + map_uint64_uint64 { key: 1 value: 100 } |
| 261 | + )pb"), |
| 262 | + DynamicGetField<TestAllTypesProto3>("map_uint64_uint64"), arena()); |
| 263 | + EXPECT_THAT(uint64_map.Find(DoubleValue(1.0), descriptor_pool(), |
| 264 | + message_factory(), arena()), |
| 265 | + IsOkAndHolds(Optional(UintValueIs(100)))); |
| 266 | + EXPECT_THAT(uint64_map.Find(DoubleValue(-1.0), descriptor_pool(), |
| 267 | + message_factory(), arena()), |
| 268 | + IsOkAndHolds(Eq(std::nullopt))); |
| 269 | + EXPECT_THAT(uint64_map.Find(DoubleValue(1e20), descriptor_pool(), |
| 270 | + message_factory(), arena()), |
| 271 | + IsOkAndHolds(Eq(std::nullopt))); |
| 272 | + |
| 273 | + ParsedMapFieldValue int32_map( |
| 274 | + DynamicParseTextProto<TestAllTypesProto3>(R"pb( |
| 275 | + map_int32_int32 { key: 1 value: 100 } |
| 276 | + )pb"), |
| 277 | + DynamicGetField<TestAllTypesProto3>("map_int32_int32"), arena()); |
| 278 | + EXPECT_THAT(int32_map.Find(DoubleValue(1.0), descriptor_pool(), |
| 279 | + message_factory(), arena()), |
| 280 | + IsOkAndHolds(Optional(IntValueIs(100)))); |
| 281 | + EXPECT_THAT(int32_map.Find(DoubleValue(1e19), descriptor_pool(), |
| 282 | + message_factory(), arena()), |
| 283 | + IsOkAndHolds(Eq(std::nullopt))); |
| 284 | + |
| 285 | + ParsedMapFieldValue uint32_map( |
| 286 | + DynamicParseTextProto<TestAllTypesProto3>(R"pb( |
| 287 | + map_uint32_uint32 { key: 1 value: 100 } |
| 288 | + )pb"), |
| 289 | + DynamicGetField<TestAllTypesProto3>("map_uint32_uint32"), arena()); |
| 290 | + EXPECT_THAT(uint32_map.Find(DoubleValue(1.0), descriptor_pool(), |
| 291 | + message_factory(), arena()), |
| 292 | + IsOkAndHolds(Optional(UintValueIs(100)))); |
| 293 | + EXPECT_THAT(uint32_map.Find(DoubleValue(-1.0), descriptor_pool(), |
| 294 | + message_factory(), arena()), |
| 295 | + IsOkAndHolds(Eq(std::nullopt))); |
| 296 | + EXPECT_THAT(uint32_map.Find(DoubleValue(1e19), descriptor_pool(), |
| 297 | + message_factory(), arena()), |
| 298 | + IsOkAndHolds(Eq(std::nullopt))); |
| 299 | +} |
| 300 | + |
228 | 301 | TEST_F(ParsedMapFieldValueTest, Has) { |
229 | 302 | ParsedMapFieldValue value( |
230 | 303 | DynamicParseTextProto<TestAllTypesProto3>(R"pb( |
|
0 commit comments