go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/proto/reflectutil/proto_path_test.go (about) 1 // Copyright 2022 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package reflectutil 16 17 import ( 18 "testing" 19 20 "google.golang.org/protobuf/reflect/protoreflect" 21 22 . "github.com/smartystreets/goconvey/convey" 23 ) 24 25 func TestPath(t *testing.T) { 26 t.Parallel() 27 28 Convey(`Path`, t, func() { 29 Convey(`can be constructed from fields`, func() { 30 desc := (&TestPathMessage{}).ProtoReflect().Descriptor() 31 fieldA := desc.Fields().ByName("single_inner") 32 fieldB := fieldA.Message().Fields().ByName("str") 33 34 pth := Path{ 35 PathField{fieldA}, 36 PathField{fieldB}, 37 } 38 39 So(pth.String(), ShouldResemble, ".single_inner.str") 40 41 msg := &TestPathMessage{SingleInner: &TestPathMessage_Inner{Str: "sup"}} 42 So(pth.Retrieve(msg), ShouldResemble, protoreflect.ValueOf("sup")) 43 }) 44 45 Convey(`supports string map fields`, func() { 46 desc := (&TestPathMessage{}).ProtoReflect().Descriptor() 47 fieldA := desc.Fields().ByName("map_inner") 48 fieldB := fieldA.MapValue().Message().Fields().ByName("str") 49 50 pth := Path{ 51 PathField{fieldA}, 52 PathMapKey(protoreflect.MapKey(protoreflect.ValueOf("neat"))), 53 PathField{fieldB}, 54 } 55 56 So(pth.String(), ShouldResemble, ".map_inner[\"neat\"].str") 57 58 msg := &TestPathMessage{MapInner: map[string]*TestPathMessage_Inner{ 59 "neat": {Str: "sup"}}, 60 } 61 So(pth.Retrieve(msg), ShouldResemble, protoreflect.ValueOf("sup")) 62 }) 63 64 Convey(`supports integer map fields`, func() { 65 desc := (&TestPathMessage{}).ProtoReflect().Descriptor() 66 fieldA := desc.Fields().ByName("int_map_inner") 67 fieldB := fieldA.MapValue().Message().Fields().ByName("str") 68 69 pth := Path{ 70 PathField{fieldA}, 71 PathMapKey(protoreflect.ValueOfInt32(100).MapKey()), 72 PathField{fieldB}, 73 } 74 75 So(pth.String(), ShouldResemble, ".int_map_inner[100].str") 76 77 msg := &TestPathMessage{IntMapInner: map[int32]*TestPathMessage_Inner{ 78 100: {Str: "sup"}}, 79 } 80 So(pth.Retrieve(msg), ShouldResemble, protoreflect.ValueOf("sup")) 81 }) 82 83 Convey(`supports repeated fields`, func() { 84 desc := (&TestPathMessage{}).ProtoReflect().Descriptor() 85 fieldA := desc.Fields().ByName("multi_inner") 86 fieldB := fieldA.Message().Fields().ByName("str") 87 88 pth := Path{ 89 PathField{fieldA}, 90 PathListIdx(2), 91 PathField{fieldB}, 92 } 93 94 So(pth.String(), ShouldResemble, ".multi_inner[2].str") 95 96 msg := &TestPathMessage{MultiInner: []*TestPathMessage_Inner{ 97 {Str: "nope"}, 98 {Str: "nope"}, 99 {Str: "sup"}, 100 }} 101 So(pth.Retrieve(msg), ShouldResemble, protoreflect.ValueOf("sup")) 102 }) 103 }) 104 }