@@ -540,6 +540,47 @@ var (
540540 "input" : "kathmandu" ,
541541 },
542542 },
543+ {
544+ name : "nested_proto_field" ,
545+ expr : `pb3.single_nested_message.bb` ,
546+ types : []proto.Message {& proto3pb.TestAllTypes {}},
547+ env : []* exprpb.Decl {
548+ decls .NewVar ("pb3" ,
549+ decls .NewObjectType ("google.expr.proto3.test.TestAllTypes" )),
550+ },
551+ in : map [string ]interface {}{
552+ "pb3" : & proto3pb.TestAllTypes {
553+ NestedType : & proto3pb.TestAllTypes_SingleNestedMessage {
554+ SingleNestedMessage : & proto3pb.TestAllTypes_NestedMessage {
555+ Bb : 1234 ,
556+ },
557+ },
558+ },
559+ },
560+ out : types .Int (1234 ),
561+ },
562+ {
563+ name : "nested_proto_field_with_index" ,
564+ expr : `pb3.map_int64_nested_type[0].child.payload.single_int32 == 1` ,
565+ types : []proto.Message {& proto3pb.TestAllTypes {}},
566+ env : []* exprpb.Decl {
567+ decls .NewVar ("pb3" ,
568+ decls .NewObjectType ("google.expr.proto3.test.TestAllTypes" )),
569+ },
570+ in : map [string ]interface {}{
571+ "pb3" : & proto3pb.TestAllTypes {
572+ MapInt64NestedType : map [int64 ]* proto3pb.NestedTestAllTypes {
573+ 0 : & proto3pb.NestedTestAllTypes {
574+ Child : & proto3pb.NestedTestAllTypes {
575+ Payload : & proto3pb.TestAllTypes {
576+ SingleInt32 : 1 ,
577+ },
578+ },
579+ },
580+ },
581+ },
582+ },
583+ },
543584 {
544585 name : "or_true_1st" ,
545586 expr : `ai == 20 || ar["foo"] == "bar"` ,
@@ -1007,6 +1048,53 @@ func TestInterpreter(t *testing.T) {
10071048 }
10081049}
10091050
1051+ func TestInterpreter_ProtoAttributeOpt (t * testing.T ) {
1052+ inst , _ , err := program (& testCase {
1053+ name : "nested_proto_field_with_index" ,
1054+ expr : `pb3.map_int64_nested_type[0].child.payload.single_int32` ,
1055+ types : []proto.Message {& proto3pb.TestAllTypes {}},
1056+ env : []* exprpb.Decl {
1057+ decls .NewVar ("pb3" ,
1058+ decls .NewObjectType ("google.expr.proto3.test.TestAllTypes" )),
1059+ },
1060+ in : map [string ]interface {}{
1061+ "pb3" : & proto3pb.TestAllTypes {
1062+ MapInt64NestedType : map [int64 ]* proto3pb.NestedTestAllTypes {
1063+ 0 : & proto3pb.NestedTestAllTypes {
1064+ Child : & proto3pb.NestedTestAllTypes {
1065+ Payload : & proto3pb.TestAllTypes {
1066+ SingleInt32 : 1 ,
1067+ },
1068+ },
1069+ },
1070+ },
1071+ },
1072+ },
1073+ }, Optimize ())
1074+ if err != nil {
1075+ t .Fatal (err )
1076+ }
1077+ attr , ok := inst .(InterpretableAttribute )
1078+ if ! ok {
1079+ t .Fatalf ("got %v, expected attribute value" , inst )
1080+ }
1081+ absAttr , ok := attr .Attr ().(NamespacedAttribute )
1082+ if ! ok {
1083+ t .Fatalf ("got %v, expected global attribute" , attr .Attr ())
1084+ }
1085+ quals := absAttr .Qualifiers ()
1086+ if len (quals ) != 5 {
1087+ t .Errorf ("got %d qualifiers, wanted 5" , len (quals ))
1088+ }
1089+ if ! isFieldQual (quals [0 ], "map_int64_nested_type" ) ||
1090+ ! isConstQual (quals [1 ], types .IntZero ) ||
1091+ ! isFieldQual (quals [2 ], "child" ) ||
1092+ ! isFieldQual (quals [3 ], "payload" ) ||
1093+ ! isFieldQual (quals [4 ], "single_int32" ) {
1094+ t .Error ("unoptimized qualifier types present in optimized attribute" )
1095+ }
1096+ }
1097+
10101098func TestInterpreter_LogicalAndMissingType (t * testing.T ) {
10111099 src := common .NewTextSource (`a && TestProto{c: true}.c` )
10121100 parsed , errors := parser .Parse (src )
@@ -1333,3 +1421,19 @@ func base64_encode(val ref.Val) ref.Val {
13331421 }
13341422 return types .String (base64 .StdEncoding .EncodeToString ([]byte (str )))
13351423}
1424+
1425+ func isConstQual (q Qualifier , val ref.Val ) bool {
1426+ c , ok := q .(ConstantQualifier )
1427+ if ! ok {
1428+ return false
1429+ }
1430+ return c .Value ().Equal (val ) == types .True
1431+ }
1432+
1433+ func isFieldQual (q Qualifier , fieldName string ) bool {
1434+ f , ok := q .(* fieldQualifier )
1435+ if ! ok {
1436+ return false
1437+ }
1438+ return f .Name == fieldName
1439+ }
0 commit comments