diff --git a/doc/langdef.md b/doc/langdef.md index ede69d3f..1c3795f0 100644 --- a/doc/langdef.md +++ b/doc/langdef.md @@ -159,10 +159,11 @@ combination of one or more of: indicate that we're accessing a field within a protocol buffer or map. * Protocol buffer package names: a simple or qualified name could represent an absolute or relative name in the protocol buffer package namespace. Package - names must be followed by a message type or enum constant. -* Protocol buffer message types and enum constants: following an optional - protocol buffer package name, a simple or qualified name could refer to a - message type or enum constant in the package's namespace. + names must be followed by a message type, enum type, or enum constant. +* Protocol buffer message types, enum types, and enum constants: following an + optional protocol buffer package name, a simple or qualified name could + refer to a message type, and enum type, or an enum constant in the + package's namespace. Resolution works as follows. If `a.b` is a name to be resolved in the context of a protobuf declaration with scope `A.B`, then resolution is attempted, in order, @@ -218,6 +219,16 @@ such as expression evaluation, rounding mode, or exception handling. However, any two not-a-number values will compare equal even if their underlying properties are different. +### Enumerations + +Each protocol buffer enumeration is its own CEL type. Enumerations have no +operations other than equality (and inequality), obtaining the type from a +value, and conversion to an `int`. (No conversion to string is supported, as +an enum value might have 0, 1, or many names.) Values of type `int` can be +converted to enum values as long as they are in the range `-2^31` to `2^31 - 1`. +A value of type `string` can be converted to enum values as long as it is a +defined for that enum. + ### String and Bytes Values Strings are sequences of Unicode code points. Bytes are sequences of octets @@ -392,11 +403,11 @@ int32, int64, sint32, sint64, sfixed32, sfixed64 | `int` uint32, uint64, fixed32, fixed64 | `uint` float, double | `double` bool, string, bytes | same -enum | `int` +enum E | E repeated | `list` map | `map` oneof | options expanded individually, at most one is set -message | same except for conversions below +message M | M, except for conversions below Signed integers, unsigned integers, and floating point numbers are converted to the singular CEL type of the same sort. The CEL type is capable of expressing @@ -406,10 +417,6 @@ buffers, an out-of-range CEL value results in an error. Boolean, string, and bytes types have identical ranges and are converted without error. -Protocol buffer enum values are converted to the corresponding `int` value. -Protocol buffer enum fields can accept any signed 32-bit number, values outside -that range will raise an error. - Repeated fields are converted to CEL lists of converted values, preserving the order. In the other direction, the CEL list elements must be of the right type and value to be converted to the corresponding protocol buffer type. Similarly, @@ -449,12 +456,12 @@ google.protobuf message | CEL Conversion `Value` | dynamically converted to the contained type (null, double, string, bool, `Struct`, or `ListValue`) wrapper types | converted as eponymous field type -The wrapper types are `BoolValue`, `BytesValue`, `DoubleValue`, `EnumValue`, -`FloatValue`, `Int32Value`, `Int64Value`, `NullValue`, `StringValue`, -`Uint32Value`, and `Uint64Value`. Values of these wrapper types are converted to -the obvious type. Additionally, field selection of an unset message field of -wrapper type will evaluate to `null`, instead of the default message. This is an -exception to the usual evaluation of unset message fields. +The wrapper types are `BoolValue`, `BytesValue`, `DoubleValue`, `FloatValue`, +`Int32Value`, `Int64Value`, `NullValue`, `StringValue`, `Uint32Value`, and +`Uint64Value`. Values of these wrapper types are converted to the obvious type. +Additionally, field selection of an unset message field of wrapper type will +evaluate to `null`, instead of the default message. This is an exception to the +usual evaluation of unset message fields. Note that this implies some cascading conversions. An `Any` message might be converted to a `Struct`, one of whose `Value`-typed values might be converted to @@ -1832,7 +1839,7 @@ See [cel-go/issues/9](https://github.com/google/cel-go/issues/9). - + int @@ -1866,6 +1873,14 @@ See [cel-go/issues/9](https://github.com/google/cel-go/issues/9). type conversion + + + (enum E) -> int + + + type conversion + + (google.protobuf.Timestamp) -> int @@ -2080,6 +2095,39 @@ See [cel-go/issues/9](https://github.com/google/cel-go/issues/9). type conversion + + + E (for fully-qualified enumeration E) + + + (int) -> enum E + + + type conversion when in int32 range, otherwise error + + + + + (string) -> enum E + + + type conversion for unqualified symbolic name, otherwise error + + + +## Appendix 1: Legacy Behavior + +### Enums + +In many pre-1.0 implementations, protocol buffer enums are all treated as CEL +type `int`, and are legal arguments whenever an `int` is expected. Int values +in the range `-2**31` to `2**31 - 1` can be used whenever an enum is expected. +Values outside that range will raise an error. There are no standard functions +for conversion from strings, and no conversion to `int` is needed. + +``` +type(google.protobuf.Field{}.kind) # was int, now google.protobuf.Field.Kind +``` diff --git a/tests/simple/testdata/enums.textproto b/tests/simple/testdata/enums.textproto index a3d84b5c..183051c5 100644 --- a/tests/simple/testdata/enums.textproto +++ b/tests/simple/testdata/enums.textproto @@ -1,2 +1,1074 @@ name: "enums" -description: "Tests for strong enum types." +description: "Tests for enum types." +section { + name: "legacy_proto2" + description: "Legacy semantics where all enums are ints, proto2." + test { + name: "literal_global" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GAZ" + value { int64_value: 2 } + } + test { + name: "literal_nested" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum.BAR" + value { int64_value: 1 } + } + test { + name: "literal_zero" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GOO" + value { int64_value: 0 } + } + test { + name: "comparision" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GAR == 1" + value { bool_value: true } + } + test { + name: "arithmetic" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum.BAR + 3" + value { int64_value: 4 } + } + test { + name: "type_global" + container: "google.api.expr.test.v1.proto2" + expr: "type(GlobalEnum.GOO)" + value { type_value: "int" } + } + test { + name: "type_nested" + container: "google.api.expr.test.v1.proto2" + expr: "type(TestAllTypes.NestedEnum.BAZ)" + value { type_value: "int" } + } + test { + name: "select_default" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.standalone_enum" + value { int64_value: 0 } + } + test { + name: "select" + container: "google.api.expr.test.v1.proto2" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: 2 + } + } + } + } + } + value { int64_value: 2 } + } + test { + name: "select_big" + container: "google.api.expr.test.v1.proto2" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: 108 + } + } + } + } + } + value { int64_value: 108 } + } + test { + name: "select_neg" + container: "google.api.expr.test.v1.proto2" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: -3 + } + } + } + } + } + value { int64_value: -3 } + } + test { + name: "field_type" + container: "google.api.expr.test.v1.proto2" + expr: "type(TestAllTypes{}.standalone_enum)" + value { type_value: "int" } + } + test { + name: "assign_standalone_name" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAZ}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: BAZ + } + } + } + } + test { + name: "assign_standalone_int" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: 1}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: BAR + } + } + } + } + test { + name: "assign_standalone_int_big" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: 99}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: 99 + } + } + } + } + test { + name: "assign_standalone_int_neg" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: -1}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: -1 + } + } + } + } + test { + name: "assign_standalone_int_too_big" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: 5000000000}" + eval_error { + errors { + message: "range" + } + } + } + test { + name: "assign_standalone_int_too_neg" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: -7000000000}" + eval_error { + errors { + message: "range" + } + } + } +} +section { + name: "legacy_proto3" + description: "Legacy semantics where all enums are ints, proto3" + test { + name: "literal_global" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GAZ" + value { int64_value: 2 } + } + test { + name: "literal_nested" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum.BAR" + value { int64_value: 1 } + } + test { + name: "literal_zero" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GOO" + value { int64_value: 0 } + } + test { + name: "comparision" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GAR == 1" + value { bool_value: true } + } + test { + name: "arithmetic" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum.BAR + 3" + value { int64_value: 4 } + } + test { + name: "type_global" + container: "google.api.expr.test.v1.proto3" + expr: "type(GlobalEnum.GOO)" + value { type_value: "int" } + } + test { + name: "type_nested" + container: "google.api.expr.test.v1.proto3" + expr: "type(TestAllTypes.NestedEnum.BAZ)" + value { type_value: "int" } + } + test { + name: "select_default" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.standalone_enum" + value { int64_value: 0 } + } + test { + name: "select" + container: "google.api.expr.test.v1.proto3" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: 2 + } + } + } + } + } + value { int64_value: 2 } + } + test { + name: "select_big" + container: "google.api.expr.test.v1.proto3" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: 108 + } + } + } + } + } + value { int64_value: 108 } + } + test { + name: "select_neg" + container: "google.api.expr.test.v1.proto3" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: -3 + } + } + } + } + } + value { int64_value: -3 } + } + test { + name: "field_type" + container: "google.api.expr.test.v1.proto3" + expr: "type(TestAllTypes{}.standalone_enum)" + value { type_value: "int" } + } + test { + name: "assign_standalone_name" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAZ}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: BAZ + } + } + } + } + test { + name: "assign_standalone_int" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: 1}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: BAR + } + } + } + } + test { + name: "assign_standalone_int_big" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: 99}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: 99 + } + } + } + } + test { + name: "assign_standalone_int_neg" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: -1}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: -1 + } + } + } + } + test { + name: "assign_standalone_int_too_big" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: 5000000000}" + eval_error { + errors { + message: "range" + } + } + } + test { + name: "assign_standalone_int_too_neg" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: -7000000000}" + eval_error { + errors { + message: "range" + } + } + } +} +section { + name: "strong_proto2" + description: "String semantics where enums are distinct types, proto2." + test { + name: "literal_global" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GAZ" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.GlobalEnum" + value: 2 + } + } + } + test { + name: "literal_nested" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum.BAR" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: 1 + } + } + } + test { + name: "literal_zero" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GOO" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.GlobalEnum" + value: 0 + } + } + } + test { + name: "comparision_true" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GAR == GlobalEnum.GAR" + value { bool_value: true } + } + test { + name: "comparision_false" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum.GAR == GlobalEnum.GAZ" + value { bool_value: false } + } + test { + name: "type_global" + container: "google.api.expr.test.v1.proto2" + expr: "type(GlobalEnum.GOO)" + value { type_value: "google.api.expr.test.v1.proto2.GlobalEnum" } + } + test { + name: "type_nested" + container: "google.api.expr.test.v1.proto2" + expr: "type(TestAllTypes.NestedEnum.BAZ)" + value { + type_value: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + } + } + test { + name: "select_default" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{}.standalone_enum" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: 0 + } + } + } + test { + name: "select" + container: "google.api.expr.test.v1.proto2" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: 2 + } + } + } + } + } + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: 2 + } + } + } + test { + name: "select_big" + container: "google.api.expr.test.v1.proto2" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: 108 + } + } + } + } + } + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: 108 + } + } + } + test { + name: "select_neg" + container: "google.api.expr.test.v1.proto2" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: -3 + } + } + } + } + } + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: -3 + } + } + } + test { + name: "field_type" + container: "google.api.expr.test.v1.proto2" + expr: "type(TestAllTypes{}.standalone_enum)" + value { + type_value: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + } + } + test { + name: "assign_standalone_name" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAZ}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: BAZ + } + } + } + } + test { + name: "assign_standalone_int" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(1)}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: BAR + } + } + } + } + test { + name: "assign_standalone_int_big" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(99)}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: 99 + } + } + } + } + test { + name: "assign_standalone_int_neg" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(-1)}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: -1 + } + } + } + } + test { + name: "convert_symbol_to_int" + container: "google.api.expr.test.v1.proto2" + expr: "int(GlobalEnum.GAZ)" + value { int64_value: 2 } + } + test { + name: "convert_unnamed_to_int" + description: "Disable check - missing way to declare enums." + expr: "int(x)" + disable_check: true + bindings { + key: "x" + value { + value { + enum_value { + type: "google.api.expr.test.v1.proto2.GlobalEnum" + value: 444 + } + } + } + } + value { int64_value: 444 } + } + test { + name: "convert_unnamed_to_int_select" + expr: "int(x.standalone_enum)" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto2.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto2.TestAllTypes] { + standalone_enum: -987 + } + } + } + } + } + value { int64_value: -987 } + } + test { + name: "convert_int_inrange" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum(2)" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: 2 + } + } + } + test { + name: "convert_int_big" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum(20000)" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: 20000 + } + } + } + test { + name: "convert_int_neg" + container: "google.api.expr.test.v1.proto2" + expr: "GlobalEnum(-33)" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.GlobalEnum" + value: -33 + } + } + } + test { + name: "convert_int_too_big" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum(5000000000)}" + eval_error { + errors { + message: "range" + } + } + } + test { + name: "convert_int_too_neg" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum(-7000000000)}" + eval_error { + errors { + message: "range" + } + } + } + test { + name: "convert_string" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum('BAZ')}" + value { + enum_value { + type: "google.api.expr.test.v1.proto2.TestAllTypes.NestedEnum" + value: 2 + } + } + } + test { + name: "convert_string_bad" + container: "google.api.expr.test.v1.proto2" + expr: "TestAllTypes.NestedEnum('BLETCH')}" + eval_error { + errors { + message: "invalid" + } + } + } +} +section { + name: "strong_proto3" + description: "String semantics where enums are distinct types, proto3." + test { + name: "literal_global" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GAZ" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.GlobalEnum" + value: 2 + } + } + } + test { + name: "literal_nested" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum.BAR" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 1 + } + } + } + test { + name: "literal_zero" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GOO" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.GlobalEnum" + value: 0 + } + } + } + test { + name: "comparision_true" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GAR == GlobalEnum.GAR" + value { bool_value: true } + } + test { + name: "comparision_false" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum.GAR == GlobalEnum.GAZ" + value { bool_value: false } + } + test { + name: "type_global" + container: "google.api.expr.test.v1.proto3" + expr: "type(GlobalEnum.GOO)" + value { type_value: "google.api.expr.test.v1.proto3.GlobalEnum" } + } + test { + name: "type_nested" + container: "google.api.expr.test.v1.proto3" + expr: "type(TestAllTypes.NestedEnum.BAZ)" + value { + type_value: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + } + } + test { + name: "select_default" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{}.standalone_enum" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 0 + } + } + } + test { + name: "select" + container: "google.api.expr.test.v1.proto3" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: 2 + } + } + } + } + } + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 2 + } + } + } + test { + name: "select_big" + container: "google.api.expr.test.v1.proto3" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: 108 + } + } + } + } + } + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 108 + } + } + } + test { + name: "select_neg" + container: "google.api.expr.test.v1.proto3" + expr: "x.standalone_enum" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: -3 + } + } + } + } + } + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: -3 + } + } + } + test { + name: "field_type" + container: "google.api.expr.test.v1.proto3" + expr: "type(TestAllTypes{}.standalone_enum)" + value { + type_value: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + } + } + test { + name: "assign_standalone_name" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum.BAZ}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: BAZ + } + } + } + } + test { + name: "assign_standalone_int" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(1)}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: BAR + } + } + } + } + test { + name: "assign_standalone_int_big" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(99)}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: 99 + } + } + } + } + test { + name: "assign_standalone_int_neg" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes{standalone_enum: TestAllTypes.NestedEnum(-1)}" + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: -1 + } + } + } + } + test { + name: "convert_symbol_to_int" + container: "google.api.expr.test.v1.proto3" + expr: "int(GlobalEnum.GAZ)" + value { int64_value: 2 } + } + test { + name: "convert_unnamed_to_int" + description: "Disable check - missing way to declare enums." + expr: "int(x)" + disable_check: true + bindings { + key: "x" + value { + value { + enum_value { + type: "google.api.expr.test.v1.proto3.GlobalEnum" + value: 444 + } + } + } + } + value { int64_value: 444 } + } + test { + name: "convert_unnamed_to_int_select" + expr: "int(x.standalone_enum)" + type_env { + name: "x" + ident { + type { message_type: "google.api.expr.test.v1.proto3.TestAllTypes" } + } + } + bindings { + key: "x" + value { + value { + object_value { + [type.googleapis.com/google.api.expr.test.v1.proto3.TestAllTypes] { + standalone_enum: -987 + } + } + } + } + } + value { int64_value: -987 } + } + test { + name: "convert_int_inrange" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum(2)" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 2 + } + } + } + test { + name: "convert_int_big" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum(20000)" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 20000 + } + } + } + test { + name: "convert_int_neg" + container: "google.api.expr.test.v1.proto3" + expr: "GlobalEnum(-33)" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.GlobalEnum" + value: -33 + } + } + } + test { + name: "convert_int_too_big" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum(5000000000)}" + eval_error { + errors { + message: "range" + } + } + } + test { + name: "convert_int_too_neg" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum(-7000000000)}" + eval_error { + errors { + message: "range" + } + } + } + test { + name: "convert_string" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum('BAZ')}" + value { + enum_value { + type: "google.api.expr.test.v1.proto3.TestAllTypes.NestedEnum" + value: 2 + } + } + } + test { + name: "convert_string_bad" + container: "google.api.expr.test.v1.proto3" + expr: "TestAllTypes.NestedEnum('BLETCH')}" + eval_error { + errors { + message: "invalid" + } + } + } +}