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  }