github.com/m3db/m3@v1.5.0/src/dbnode/encoding/proto/custom_unmarshal_test.go (about) 1 // Copyright (c) 2019 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package proto 22 23 import ( 24 "bytes" 25 "math" 26 "testing" 27 "time" 28 29 "github.com/jhump/protoreflect/dynamic" 30 "github.com/stretchr/testify/require" 31 ) 32 33 func TestCustomFieldUnmarshaller(t *testing.T) { 34 // Store in a var to prevent the compiler from complaining about overflow errors. 35 neg1 := -1 36 37 testCases := []struct { 38 timestamp time.Time 39 latitude float64 40 longitude float64 41 epoch int64 42 deliveryID []byte 43 attributes map[string]string 44 45 expectedSortedCustomFields []unmarshalValue 46 }{ 47 { 48 latitude: 0.1, 49 longitude: 1.1, 50 epoch: -1, 51 52 expectedSortedCustomFields: []unmarshalValue{ 53 { 54 fieldNumber: 1, 55 v: math.Float64bits(0.1), 56 }, 57 { 58 fieldNumber: 2, 59 v: math.Float64bits(1.1), 60 }, 61 { 62 fieldNumber: 3, 63 v: uint64(neg1), 64 }, 65 }, 66 }, 67 { 68 latitude: 0.1, 69 longitude: 1.1, 70 epoch: 0, 71 deliveryID: []byte("123123123123"), 72 73 expectedSortedCustomFields: []unmarshalValue{ 74 { 75 fieldNumber: 1, 76 v: math.Float64bits(0.1), 77 }, 78 { 79 fieldNumber: 2, 80 v: math.Float64bits(1.1), 81 }, 82 // Note that epoch (field number 3) is not included here because default 83 // value are not included in a marshalled protobuf stream (their absence 84 // implies a default vlaue for a field) which means they're also not 85 // returned by the `sortedCustomFieldValues` method. 86 { 87 fieldNumber: 4, 88 bytes: []byte("123123123123"), 89 }, 90 }, 91 }, 92 { 93 latitude: 0.2, 94 longitude: 2.2, 95 epoch: 1, 96 deliveryID: []byte("789789789789"), 97 attributes: map[string]string{"key1": "val1"}, 98 99 expectedSortedCustomFields: []unmarshalValue{ 100 { 101 fieldNumber: 1, 102 v: math.Float64bits(0.2), 103 }, 104 { 105 fieldNumber: 2, 106 v: math.Float64bits(2.2), 107 }, 108 { 109 fieldNumber: 3, 110 v: (1), 111 }, 112 { 113 fieldNumber: 4, 114 bytes: []byte("789789789789"), 115 }, 116 }, 117 }, 118 } 119 120 unmarshaller := newCustomFieldUnmarshaller(customUnmarshallerOptions{}) 121 for _, tc := range testCases { 122 vl := newVL( 123 tc.latitude, tc.longitude, tc.epoch, tc.deliveryID, tc.attributes) 124 marshalledVL, err := vl.Marshal() 125 require.NoError(t, err) 126 127 unmarshaller.resetAndUnmarshal(testVLSchema, marshalledVL) 128 sortedCustomFieldValues := unmarshaller.sortedCustomFieldValues() 129 require.Equal(t, len(tc.expectedSortedCustomFields), len(sortedCustomFieldValues)) 130 131 lastFieldNum := -1 132 for i, curr := range sortedCustomFieldValues { 133 var ( 134 fieldNum = curr.fieldNumber 135 expected = tc.expectedSortedCustomFields[i] 136 ) 137 // Make sure iteration is sorted and values match. 138 require.True(t, int(fieldNum) > lastFieldNum) 139 require.Equal(t, expected, curr) 140 switch fieldNum { 141 case 1: 142 require.Equal(t, tc.latitude, curr.asFloat64()) 143 case 2: 144 require.Equal(t, tc.longitude, curr.asFloat64()) 145 case 3: 146 require.Equal(t, tc.epoch, curr.asInt64()) 147 case 4: 148 require.True(t, bytes.Equal(tc.deliveryID, curr.asBytes())) 149 } 150 i++ 151 } 152 153 if len(tc.attributes) > 0 { 154 require.Equal(t, len(tc.attributes), unmarshaller.numNonCustomValues()) 155 nonCustomFieldValues := unmarshaller.sortedNonCustomFieldValues() 156 require.Equal(t, 1, len(nonCustomFieldValues)) 157 require.Equal(t, int32(5), nonCustomFieldValues[0].fieldNum) 158 159 assertAttributesEqualMarshalledBytes( 160 t, 161 nonCustomFieldValues[0].marshalled, 162 tc.attributes) 163 } else { 164 require.Equal(t, 0, unmarshaller.numNonCustomValues()) 165 } 166 } 167 } 168 169 func assertAttributesEqualMarshalledBytes( 170 t *testing.T, 171 actualMarshalled []byte, 172 attrs map[string]string, 173 ) { 174 m := dynamic.NewMessage(testVLSchema) 175 m.SetFieldByName("attributes", attrs) 176 expectedMarshalled, err := m.Marshal() 177 178 require.NoError(t, err) 179 require.Equal(t, expectedMarshalled, actualMarshalled) 180 }