github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-config/protolator/json_test.go (about) 1 /* 2 Copyright IBM Corp. 2017 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package protolator 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "fmt" 23 "github.com/hellobchain/third_party/hyperledger/fabric-config/protolator/testprotos" 24 "math" 25 "reflect" 26 "testing" 27 28 "github.com/golang/protobuf/proto" 29 . "github.com/onsi/gomega" 30 ) 31 32 type testProtoPlainFieldFactory struct { 33 fromPrefix string 34 toPrefix string 35 fromError error 36 toError error 37 } 38 39 func (tpff *testProtoPlainFieldFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool { 40 return fieldName == "plain_field" 41 } 42 43 func (tpff *testProtoPlainFieldFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) { 44 return &plainField{ 45 baseField: baseField{ 46 msg: msg, 47 name: fieldName, 48 fType: reflect.TypeOf(""), 49 vType: fieldType, 50 value: fieldValue, 51 }, 52 populateFrom: func(source interface{}, destType reflect.Type) (reflect.Value, error) { 53 sourceAsString := source.(string) 54 return reflect.ValueOf(tpff.fromPrefix + sourceAsString), tpff.fromError 55 }, 56 populateTo: func(source reflect.Value) (interface{}, error) { 57 return tpff.toPrefix + source.Interface().(string), tpff.toError 58 }, 59 }, nil 60 } 61 62 func TestSimpleMsgPlainField(t *testing.T) { 63 gt := NewGomegaWithT(t) 64 65 fromPrefix := "from" 66 toPrefix := "to" 67 tppff := &testProtoPlainFieldFactory{ 68 fromPrefix: fromPrefix, 69 toPrefix: toPrefix, 70 } 71 72 fieldFactories = []protoFieldFactory{tppff} 73 74 pfValue := "foo" 75 startMsg := &testprotos.SimpleMsg{ 76 PlainField: pfValue, 77 MapField: map[string]string{"1": "2"}, 78 SliceField: []string{"a", "b"}, 79 } 80 81 var buffer bytes.Buffer 82 err := DeepMarshalJSON(&buffer, startMsg) 83 gt.Expect(err).NotTo(HaveOccurred()) 84 85 newMsg := &testprotos.SimpleMsg{} 86 err = DeepUnmarshalJSON(bytes.NewReader(buffer.Bytes()), newMsg) 87 gt.Expect(err).NotTo(HaveOccurred()) 88 89 gt.Expect(newMsg.MapField).To(Equal(startMsg.MapField)) 90 gt.Expect(newMsg.SliceField).To(Equal(startMsg.SliceField)) 91 gt.Expect(newMsg.PlainField).To(Equal(fromPrefix + toPrefix + startMsg.PlainField)) 92 93 tppff.fromError = fmt.Errorf("Failing from intentionally") 94 err = DeepUnmarshalJSON(bytes.NewReader(buffer.Bytes()), newMsg) 95 gt.Expect(err).To(MatchError("*testprotos.SimpleMsg: error in PopulateFrom for field plain_field for message *testprotos.SimpleMsg: Failing from intentionally")) 96 97 tppff.toError = fmt.Errorf("Failing to intentionally") 98 err = DeepMarshalJSON(&buffer, startMsg) 99 gt.Expect(err).To(MatchError("*testprotos.SimpleMsg: error in PopulateTo for field plain_field for message *testprotos.SimpleMsg: Failing to intentionally")) 100 } 101 102 type testProtoMapFieldFactory struct { 103 fromPrefix string 104 toPrefix string 105 fromError error 106 toError error 107 } 108 109 func (tpff *testProtoMapFieldFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool { 110 return fieldName == "map_field" 111 } 112 113 func (tpff *testProtoMapFieldFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) { 114 return &mapField{ 115 baseField: baseField{ 116 msg: msg, 117 name: fieldName, 118 fType: reflect.TypeOf(""), 119 vType: fieldType, 120 value: fieldValue, 121 }, 122 populateFrom: func(key string, source interface{}, destType reflect.Type) (reflect.Value, error) { 123 sourceAsString := source.(string) 124 return reflect.ValueOf(tpff.fromPrefix + key + sourceAsString), tpff.fromError 125 }, 126 populateTo: func(key string, source reflect.Value) (interface{}, error) { 127 return tpff.toPrefix + key + source.Interface().(string), tpff.toError 128 }, 129 }, nil 130 } 131 132 func TestSimpleMsgMapField(t *testing.T) { 133 gt := NewGomegaWithT(t) 134 135 fromPrefix := "from" 136 toPrefix := "to" 137 tpmff := &testProtoMapFieldFactory{ 138 fromPrefix: fromPrefix, 139 toPrefix: toPrefix, 140 } 141 fieldFactories = []protoFieldFactory{tpmff} 142 143 key := "foo" 144 value := "bar" 145 startMsg := &testprotos.SimpleMsg{ 146 PlainField: "1", 147 MapField: map[string]string{key: value}, 148 SliceField: []string{"a", "b"}, 149 } 150 151 var buffer bytes.Buffer 152 err := DeepMarshalJSON(&buffer, startMsg) 153 gt.Expect(err).NotTo(HaveOccurred()) 154 155 newMsg := &testprotos.SimpleMsg{} 156 err = DeepUnmarshalJSON(bytes.NewReader(buffer.Bytes()), newMsg) 157 gt.Expect(err).NotTo(HaveOccurred()) 158 159 gt.Expect(newMsg.PlainField).To(Equal(startMsg.PlainField)) 160 gt.Expect(newMsg.SliceField).To(Equal(startMsg.SliceField)) 161 gt.Expect(newMsg.MapField[key]).To(Equal(fromPrefix + key + toPrefix + key + startMsg.MapField[key])) 162 163 tpmff.fromError = fmt.Errorf("Failing from intentionally") 164 err = DeepUnmarshalJSON(bytes.NewReader(buffer.Bytes()), newMsg) 165 gt.Expect(err).To(MatchError("*testprotos.SimpleMsg: error in PopulateFrom for map field map_field with key foo for message *testprotos.SimpleMsg: Failing from intentionally")) 166 167 tpmff.toError = fmt.Errorf("Failing to intentionally") 168 err = DeepMarshalJSON(&buffer, startMsg) 169 gt.Expect(err).To(MatchError("*testprotos.SimpleMsg: error in PopulateTo for map field map_field and key foo for message *testprotos.SimpleMsg: Failing to intentionally")) 170 } 171 172 type testProtoSliceFieldFactory struct { 173 fromPrefix string 174 toPrefix string 175 fromError error 176 toError error 177 } 178 179 func (tpff *testProtoSliceFieldFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool { 180 return fieldName == "slice_field" 181 } 182 183 func (tpff *testProtoSliceFieldFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) { 184 return &sliceField{ 185 baseField: baseField{ 186 msg: msg, 187 name: fieldName, 188 fType: reflect.TypeOf(""), 189 vType: fieldType, 190 value: fieldValue, 191 }, 192 populateFrom: func(index int, source interface{}, destType reflect.Type) (reflect.Value, error) { 193 sourceAsString := source.(string) 194 return reflect.ValueOf(tpff.fromPrefix + fmt.Sprintf("%d", index) + sourceAsString), tpff.fromError 195 }, 196 populateTo: func(index int, source reflect.Value) (interface{}, error) { 197 return tpff.toPrefix + fmt.Sprintf("%d", index) + source.Interface().(string), tpff.toError 198 }, 199 }, nil 200 } 201 202 func TestSimpleMsgSliceField(t *testing.T) { 203 gt := NewGomegaWithT(t) 204 205 fromPrefix := "from" 206 toPrefix := "to" 207 tpsff := &testProtoSliceFieldFactory{ 208 fromPrefix: fromPrefix, 209 toPrefix: toPrefix, 210 } 211 fieldFactories = []protoFieldFactory{tpsff} 212 213 value := "foo" 214 startMsg := &testprotos.SimpleMsg{ 215 PlainField: "1", 216 MapField: map[string]string{"a": "b"}, 217 SliceField: []string{value}, 218 } 219 220 var buffer bytes.Buffer 221 err := DeepMarshalJSON(&buffer, startMsg) 222 gt.Expect(err).NotTo(HaveOccurred()) 223 224 newMsg := &testprotos.SimpleMsg{} 225 err = DeepUnmarshalJSON(bytes.NewReader(buffer.Bytes()), newMsg) 226 gt.Expect(err).NotTo(HaveOccurred()) 227 228 gt.Expect(newMsg.PlainField).To(Equal(startMsg.PlainField)) 229 gt.Expect(newMsg.MapField).To(Equal(startMsg.MapField)) 230 gt.Expect(newMsg.SliceField[0]).To(Equal(fromPrefix + "0" + toPrefix + "0" + startMsg.SliceField[0])) 231 232 tpsff.fromError = fmt.Errorf("Failing from intentionally") 233 err = DeepUnmarshalJSON(bytes.NewReader(buffer.Bytes()), newMsg) 234 gt.Expect(err).To(MatchError("*testprotos.SimpleMsg: error in PopulateFrom for slice field slice_field at index 0 for message *testprotos.SimpleMsg: Failing from intentionally")) 235 236 tpsff.toError = fmt.Errorf("Failing to intentionally") 237 err = DeepMarshalJSON(&buffer, startMsg) 238 gt.Expect(err).To(MatchError("*testprotos.SimpleMsg: error in PopulateTo for slice field slice_field at index 0 for message *testprotos.SimpleMsg: Failing to intentionally")) 239 } 240 241 type testProtoFailFactory struct{} 242 243 func (tpff testProtoFailFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool { 244 return true 245 } 246 247 func (tpff testProtoFailFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) { 248 return nil, fmt.Errorf("Intentionally failing") 249 } 250 251 func TestFailFactory(t *testing.T) { 252 gt := NewGomegaWithT(t) 253 254 fieldFactories = []protoFieldFactory{&testProtoFailFactory{}} 255 256 var buffer bytes.Buffer 257 err := DeepMarshalJSON(&buffer, &testprotos.SimpleMsg{}) 258 gt.Expect(err).To(MatchError("*testprotos.SimpleMsg: Intentionally failing")) 259 } 260 261 func TestJSONUnmarshalMaxUint32(t *testing.T) { 262 gt := NewGomegaWithT(t) 263 264 fieldName := "numField" 265 jsonString := fmt.Sprintf("{\"%s\":%d}", fieldName, math.MaxUint32) 266 m, err := jsonToMap([]byte(jsonString)) 267 gt.Expect(err).NotTo(HaveOccurred()) 268 gt.Expect(m[fieldName]).To(BeAssignableToTypeOf(json.Number(""))) 269 } 270 271 func TestMostlyDeterministicMarshal(t *testing.T) { 272 gt := NewGomegaWithT(t) 273 274 multiKeyMap := &testprotos.SimpleMsg{ 275 MapField: map[string]string{ 276 "a": "b", 277 "c": "d", 278 "e": "f", 279 "g": "h", 280 "i": "j", 281 "k": "l", 282 "m": "n", 283 "o": "p", 284 "q": "r", 285 "s": "t", 286 "u": "v", 287 "w": "x", 288 "y": "z", 289 }, 290 } 291 292 result, err := MostlyDeterministicMarshal(multiKeyMap) 293 gt.Expect(err).NotTo(HaveOccurred()) 294 gt.Expect(result).NotTo(BeNil()) 295 296 // Golang map marshaling is non-deterministic by default, by marshaling 297 // the same message with an embedded map multiple times, we should 298 // detect a mismatch if the default behavior persists. Even with 3 map 299 // elements, there is usually a mismatch within 2-3 iterations, so 13 300 // entries and 10 iterations seems like a reasonable check. 301 for i := 0; i < 10; i++ { 302 newResult, err := MostlyDeterministicMarshal(multiKeyMap) 303 gt.Expect(err).NotTo(HaveOccurred()) 304 gt.Expect(newResult).To(Equal(result)) 305 } 306 307 unmarshaled := &testprotos.SimpleMsg{} 308 err = proto.Unmarshal(result, unmarshaled) 309 gt.Expect(err).NotTo(HaveOccurred()) 310 gt.Expect(proto.Equal(unmarshaled, multiKeyMap)).To(BeTrue()) 311 }