github.com/yimialmonte/fabric@v2.1.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  }