github.com/kaituanwang/hyperledger@v2.0.1+incompatible/common/tools/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 "math" 24 "reflect" 25 "testing" 26 27 "github.com/golang/protobuf/proto" 28 "github.com/hyperledger/fabric/common/tools/protolator/testprotos" 29 "github.com/stretchr/testify/assert" 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 fromPrefix := "from" 64 toPrefix := "to" 65 tppff := &testProtoPlainFieldFactory{ 66 fromPrefix: fromPrefix, 67 toPrefix: toPrefix, 68 } 69 70 fieldFactories = []protoFieldFactory{tppff} 71 72 pfValue := "foo" 73 startMsg := &testprotos.SimpleMsg{ 74 PlainField: pfValue, 75 MapField: map[string]string{"1": "2"}, 76 SliceField: []string{"a", "b"}, 77 } 78 79 var buffer bytes.Buffer 80 assert.NoError(t, DeepMarshalJSON(&buffer, startMsg)) 81 82 newMsg := &testprotos.SimpleMsg{} 83 assert.NoError(t, DeepUnmarshalJSON(bytes.NewReader(buffer.Bytes()), newMsg)) 84 85 assert.Equal(t, startMsg.MapField, newMsg.MapField) 86 assert.Equal(t, startMsg.SliceField, newMsg.SliceField) 87 assert.Equal(t, fromPrefix+toPrefix+startMsg.PlainField, newMsg.PlainField) 88 89 tppff.fromError = fmt.Errorf("Failing from intentionally") 90 assert.Error(t, DeepUnmarshalJSON(bytes.NewReader(buffer.Bytes()), newMsg)) 91 92 tppff.toError = fmt.Errorf("Failing to intentionally") 93 assert.Error(t, DeepMarshalJSON(&buffer, startMsg)) 94 } 95 96 type testProtoMapFieldFactory struct { 97 fromPrefix string 98 toPrefix string 99 fromError error 100 toError error 101 } 102 103 func (tpff *testProtoMapFieldFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool { 104 return fieldName == "map_field" 105 } 106 107 func (tpff *testProtoMapFieldFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) { 108 return &mapField{ 109 baseField: baseField{ 110 msg: msg, 111 name: fieldName, 112 fType: reflect.TypeOf(""), 113 vType: fieldType, 114 value: fieldValue, 115 }, 116 populateFrom: func(key string, source interface{}, destType reflect.Type) (reflect.Value, error) { 117 sourceAsString := source.(string) 118 return reflect.ValueOf(tpff.fromPrefix + key + sourceAsString), tpff.fromError 119 }, 120 populateTo: func(key string, source reflect.Value) (interface{}, error) { 121 return tpff.toPrefix + key + source.Interface().(string), tpff.toError 122 }, 123 }, nil 124 } 125 126 func TestSimpleMsgMapField(t *testing.T) { 127 fromPrefix := "from" 128 toPrefix := "to" 129 tpmff := &testProtoMapFieldFactory{ 130 fromPrefix: fromPrefix, 131 toPrefix: toPrefix, 132 } 133 fieldFactories = []protoFieldFactory{tpmff} 134 135 key := "foo" 136 value := "bar" 137 startMsg := &testprotos.SimpleMsg{ 138 PlainField: "1", 139 MapField: map[string]string{key: value}, 140 SliceField: []string{"a", "b"}, 141 } 142 143 var buffer bytes.Buffer 144 assert.NoError(t, DeepMarshalJSON(&buffer, startMsg)) 145 146 newMsg := &testprotos.SimpleMsg{} 147 assert.NoError(t, DeepUnmarshalJSON(bytes.NewReader(buffer.Bytes()), newMsg)) 148 149 assert.Equal(t, startMsg.PlainField, newMsg.PlainField) 150 assert.Equal(t, startMsg.SliceField, newMsg.SliceField) 151 assert.Equal(t, fromPrefix+key+toPrefix+key+startMsg.MapField[key], newMsg.MapField[key]) 152 153 tpmff.fromError = fmt.Errorf("Failing from intentionally") 154 assert.Error(t, DeepUnmarshalJSON(bytes.NewReader(buffer.Bytes()), newMsg)) 155 156 tpmff.toError = fmt.Errorf("Failing to intentionally") 157 assert.Error(t, DeepMarshalJSON(&buffer, startMsg)) 158 } 159 160 type testProtoSliceFieldFactory struct { 161 fromPrefix string 162 toPrefix string 163 fromError error 164 toError error 165 } 166 167 func (tpff *testProtoSliceFieldFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool { 168 return fieldName == "slice_field" 169 } 170 171 func (tpff *testProtoSliceFieldFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) { 172 return &sliceField{ 173 baseField: baseField{ 174 msg: msg, 175 name: fieldName, 176 fType: reflect.TypeOf(""), 177 vType: fieldType, 178 value: fieldValue, 179 }, 180 populateFrom: func(index int, source interface{}, destType reflect.Type) (reflect.Value, error) { 181 sourceAsString := source.(string) 182 return reflect.ValueOf(tpff.fromPrefix + fmt.Sprintf("%d", index) + sourceAsString), tpff.fromError 183 }, 184 populateTo: func(index int, source reflect.Value) (interface{}, error) { 185 return tpff.toPrefix + fmt.Sprintf("%d", index) + source.Interface().(string), tpff.toError 186 }, 187 }, nil 188 } 189 190 func TestSimpleMsgSliceField(t *testing.T) { 191 fromPrefix := "from" 192 toPrefix := "to" 193 tpsff := &testProtoSliceFieldFactory{ 194 fromPrefix: fromPrefix, 195 toPrefix: toPrefix, 196 } 197 fieldFactories = []protoFieldFactory{tpsff} 198 199 value := "foo" 200 startMsg := &testprotos.SimpleMsg{ 201 PlainField: "1", 202 MapField: map[string]string{"a": "b"}, 203 SliceField: []string{value}, 204 } 205 206 var buffer bytes.Buffer 207 assert.NoError(t, DeepMarshalJSON(&buffer, startMsg)) 208 209 newMsg := &testprotos.SimpleMsg{} 210 assert.NoError(t, DeepUnmarshalJSON(bytes.NewReader(buffer.Bytes()), newMsg)) 211 212 assert.Equal(t, startMsg.PlainField, newMsg.PlainField) 213 assert.Equal(t, startMsg.MapField, newMsg.MapField) 214 assert.Equal(t, fromPrefix+"0"+toPrefix+"0"+startMsg.SliceField[0], newMsg.SliceField[0]) 215 216 tpsff.fromError = fmt.Errorf("Failing from intentionally") 217 assert.Error(t, DeepUnmarshalJSON(bytes.NewReader(buffer.Bytes()), newMsg)) 218 219 tpsff.toError = fmt.Errorf("Failing to intentionally") 220 assert.Error(t, DeepMarshalJSON(&buffer, startMsg)) 221 } 222 223 type testProtoFailFactory struct{} 224 225 func (tpff testProtoFailFactory) Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool { 226 return true 227 } 228 229 func (tpff testProtoFailFactory) NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error) { 230 return nil, fmt.Errorf("Intentionally failing") 231 } 232 233 func TestFailFactory(t *testing.T) { 234 fieldFactories = []protoFieldFactory{&testProtoFailFactory{}} 235 236 var buffer bytes.Buffer 237 assert.Error(t, DeepMarshalJSON(&buffer, &testprotos.SimpleMsg{})) 238 } 239 240 func TestJSONUnmarshalMaxUint32(t *testing.T) { 241 fieldName := "numField" 242 jsonString := fmt.Sprintf("{\"%s\":%d}", fieldName, math.MaxUint32) 243 m, err := jsonToMap([]byte(jsonString)) 244 assert.NoError(t, err) 245 assert.IsType(t, json.Number(""), m[fieldName]) 246 } 247 248 func TestMostlyDeterministicMarshal(t *testing.T) { 249 multiKeyMap := &testprotos.SimpleMsg{ 250 MapField: map[string]string{ 251 "a": "b", 252 "c": "d", 253 "e": "f", 254 "g": "h", 255 "i": "j", 256 "k": "l", 257 "m": "n", 258 "o": "p", 259 "q": "r", 260 "s": "t", 261 "u": "v", 262 "w": "x", 263 "y": "z", 264 }, 265 } 266 267 result, err := MostlyDeterministicMarshal(multiKeyMap) 268 assert.NoError(t, err) 269 assert.NotNil(t, result) 270 271 // Golang map marshaling is non-deterministic by default, by marshaling 272 // the same message with an embedded map multiple times, we should 273 // detect a mismatch if the default behavior persists. Even with 3 map 274 // elements, there is usually a mismatch within 2-3 iterations, so 13 275 // entries and 10 iterations seems like a reasonable check. 276 for i := 0; i < 10; i++ { 277 newResult, err := MostlyDeterministicMarshal(multiKeyMap) 278 assert.NoError(t, err) 279 assert.Equal(t, result, newResult) 280 } 281 282 unmarshaled := &testprotos.SimpleMsg{} 283 err = proto.Unmarshal(result, unmarshaled) 284 assert.NoError(t, err) 285 assert.True(t, proto.Equal(unmarshaled, multiKeyMap)) 286 }