github.com/cosmos/cosmos-proto@v1.0.0-beta.3/testpb/range_test.go (about) 1 package testpb 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/require" 7 "google.golang.org/protobuf/proto" 8 "google.golang.org/protobuf/reflect/protoreflect" 9 "google.golang.org/protobuf/types/dynamicpb" 10 ) 11 12 func TestRange(t *testing.T) { 13 t.Run("empty", func(t *testing.T) { 14 dyn := dynamicpb.NewMessage(md_A) 15 msg := (&A{}).ProtoReflect() 16 17 dynV := map[protoreflect.FieldDescriptor]protoreflect.Value{} 18 msgV := map[protoreflect.FieldDescriptor]protoreflect.Value{} 19 20 dyn.Range(func(descriptor protoreflect.FieldDescriptor, value protoreflect.Value) bool { 21 dynV[descriptor] = value 22 return true 23 }) 24 25 msg.Range(func(descriptor protoreflect.FieldDescriptor, value protoreflect.Value) bool { 26 msgV[descriptor] = protoreflect.Value{} 27 return true 28 }) 29 30 require.Equal(t, len(dynV), len(msgV)) 31 require.Equal(t, len(msgV), 0) 32 }) 33 34 t.Run("all fields filled", func(t *testing.T) { 35 // create a message which has all fields set 36 // and copy it to dynamicpb message 37 msg := &A{ 38 Enum: Enumeration_Two, 39 SomeBoolean: true, 40 INT32: 1, 41 SINT32: 2, 42 UINT32: 3, 43 INT64: 4, 44 SING64: 5, 45 UINT64: 6, 46 SFIXED32: 7, 47 FIXED32: 8, 48 FLOAT: 9, 49 SFIXED64: 10, 50 FIXED64: 11, 51 DOUBLE: 12, 52 STRING: "a string", 53 BYTES: []byte("test bytes"), 54 MESSAGE: &B{ 55 X: "something else", 56 }, 57 MAP: map[string]*B{"item": {X: "inside_map_item"}}, 58 LIST: []*B{{X: "part of list"}}, 59 ONEOF: &A_ONEOF_B{ONEOF_B: &B{X: "1"}}, 60 LIST_ENUM: []Enumeration{Enumeration_One, Enumeration_One}, 61 } 62 63 dyn := dynamicpb.NewMessage(msg.ProtoReflect().Descriptor()) 64 65 b, err := proto.MarshalOptions{}.Marshal(msg) 66 require.NoError(t, err) 67 require.NoError(t, proto.Unmarshal(b, dyn)) 68 69 dynV := map[protoreflect.FieldDescriptor]protoreflect.Value{} 70 msgV := map[protoreflect.FieldDescriptor]protoreflect.Value{} 71 72 dyn.Range(func(descriptor protoreflect.FieldDescriptor, value protoreflect.Value) bool { 73 dynV[descriptor] = value 74 return true 75 }) 76 77 msg.ProtoReflect().Range(func(descriptor protoreflect.FieldDescriptor, value protoreflect.Value) bool { 78 msgV[descriptor] = value 79 return true 80 }) 81 82 require.Equal(t, len(dynV), len(msgV)) 83 84 // assert field equality 85 for field, dynValue := range dynV { 86 msgValue, exists := msgV[field] 87 require.True(t, exists, "field ", field.FullName(), "not found") 88 89 valueEquality(t, field, dynValue, msgValue) 90 } 91 }) 92 } 93 94 func valueEquality(t *testing.T, field protoreflect.FieldDescriptor, v1, v2 protoreflect.Value) { 95 if !v1.IsValid() { 96 require.False(t, v2.IsValid()) 97 return 98 } 99 100 switch { 101 case field.IsList(): 102 list1 := v1.List() 103 list2 := v2.List() 104 105 if !list1.IsValid() { 106 require.False(t, list2.IsValid()) 107 return 108 } 109 110 require.Equal(t, list1.Len(), list2.Len()) 111 112 for i := 0; i < list1.Len(); i++ { 113 elem1 := list1.Get(i) 114 elem2 := list2.Get(i) 115 116 // note: we cannot call again valueEquality otherwise we end up in a loop 117 switch { 118 case field.Kind() == protoreflect.MessageKind: 119 require.True(t, proto.Equal(elem1.Message().Interface(), elem2.Message().Interface())) 120 default: 121 require.Equal(t, elem1.Interface(), elem2.Interface()) 122 } 123 } 124 case field.IsMap(): 125 map1 := v1.Map() 126 map2 := v2.Map() 127 128 if !map1.IsValid() { 129 require.False(t, map2.IsValid()) 130 return 131 } 132 133 require.Equal(t, map1.Len(), map2.Len()) 134 135 map1.Range(func(key protoreflect.MapKey, map1Value protoreflect.Value) bool { 136 // assert map2 has the key from map1 137 map2Value := map2.Get(key) 138 require.True(t, map2Value.IsValid(), "key not found", key) 139 140 // assert the values are equal 141 valueEquality(t, field.MapValue(), map1Value, map2Value) 142 return true 143 }) 144 case field.Kind() == protoreflect.MessageKind: 145 if !v1.Message().IsValid() { 146 require.False(t, v2.Message().IsValid()) 147 return 148 } 149 require.True(t, proto.Equal(v1.Message().Interface(), v2.Message().Interface())) 150 default: 151 require.Equal(t, v1.Interface(), v2.Interface()) 152 } 153 }