github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/iavl/tree_delta_encoder_test.go (about) 1 package iavl 2 3 import ( 4 "fmt" 5 "math" 6 "testing" 7 8 "github.com/stretchr/testify/require" 9 10 "github.com/fibonacci-chain/fbc/libs/tendermint/types" 11 ) 12 13 var testTreeDeltaMap = []TreeDeltaMap{ 14 //empty 15 {}, 16 //nil treedelta 17 { 18 "test1": nil, 19 }, 20 //empty treedelta 21 { 22 "test2": {}, 23 }, 24 //empty NodesDelta 25 { 26 "test3": { 27 NodesDelta: []*NodeJsonImp{}, 28 OrphansDelta: []*NodeJson{{Version: 3}, {Version: 4}}, 29 CommitOrphansDelta: []*CommitOrphansImp{{"nd1", 1}, {"nd2", 2}}, 30 }, 31 }, 32 //empty OrphansDelta 33 { 34 "test4": { 35 NodesDelta: []*NodeJsonImp{ 36 {"nd1", &NodeJson{Version: 1}}, 37 {"nd2", &NodeJson{Version: 2}}, 38 }, 39 OrphansDelta: []*NodeJson{}, 40 CommitOrphansDelta: []*CommitOrphansImp{{"nd1", 1}, {"nd2", 2}}, 41 }, 42 }, 43 //empty CommitOrphansDelta 44 { 45 "test5": { 46 NodesDelta: []*NodeJsonImp{ 47 {"nd1", &NodeJson{Version: 1}}, 48 {"nd2", &NodeJson{Version: 2}}, 49 }, 50 OrphansDelta: []*NodeJson{{Version: 3}, {Version: 4}}, 51 CommitOrphansDelta: []*CommitOrphansImp{}, 52 }, 53 }, 54 // some empty data in slice 55 { 56 "test6": { 57 NodesDelta: []*NodeJsonImp{ 58 {"nd1", &NodeJson{Version: 1}}, 59 {}, 60 nil, 61 {"nd2", &NodeJson{Version: 2}}, 62 }, 63 OrphansDelta: []*NodeJson{{Version: 3}, {}, nil, {Version: 4}}, 64 CommitOrphansDelta: []*CommitOrphansImp{{"nd1", 1}, {}, nil, {"nd2", 2}}, 65 }, 66 }, 67 68 // full data 69 { 70 "test7": { 71 NodesDelta: []*NodeJsonImp{ 72 {"nd1", &NodeJson{Version: 1}}, 73 {"nd2", &NodeJson{Version: 2}}, 74 }, 75 OrphansDelta: []*NodeJson{{Version: 3}, {Version: 4}}, 76 CommitOrphansDelta: []*CommitOrphansImp{{"nd1", 1}, {"nd2", 2}}, 77 }, 78 }, 79 // multiple data 80 { 81 "test8.0": { 82 NodesDelta: []*NodeJsonImp{ 83 {"nd1", &NodeJson{Version: 1}}, 84 {"nd2", &NodeJson{Version: 2}}, 85 }, 86 OrphansDelta: []*NodeJson{{Version: 3}, {Version: 4}}, 87 CommitOrphansDelta: []*CommitOrphansImp{{"nd1", 1}, {"nd2", 2}}, 88 }, 89 "test8.1": { 90 NodesDelta: []*NodeJsonImp{ 91 {"nd3", &NodeJson{Version: 3}}, 92 }, 93 OrphansDelta: []*NodeJson{{Version: 5}}, 94 CommitOrphansDelta: []*CommitOrphansImp{{"nd1", 3}}, 95 }, 96 }, 97 } 98 99 func newTestTreeDeltaMap() TreeDeltaMap { 100 return testTreeDeltaMap[len(testTreeDeltaMap)-1] 101 } 102 103 // test map[string]*TreeDelta amino 104 func TestTreeDeltaMapAmino(t *testing.T) { testTreeDeltaMapAmino(t) } 105 func testTreeDeltaMapAmino(t *testing.T) { 106 for i, tdm := range testTreeDeltaMap { 107 expect, err := cdc.MarshalBinaryBare(tdm) 108 require.NoError(t, err, fmt.Sprintf("num %v", i)) 109 110 actual, err := tdm.MarshalToAmino(cdc) 111 require.NoError(t, err, fmt.Sprintf("num %v", i)) 112 require.EqualValues(t, expect, actual, fmt.Sprintf("num %v", i)) 113 114 expectValue := TreeDeltaMap{} 115 err = cdc.UnmarshalBinaryBare(expect, &expectValue) 116 require.NoError(t, err, fmt.Sprintf("num %v", i)) 117 118 actualValue := TreeDeltaMap{} 119 err = actualValue.UnmarshalFromAmino(cdc, expect) 120 require.NoError(t, err, fmt.Sprintf("num %v", i)) 121 require.EqualValues(t, expectValue, actualValue, fmt.Sprintf("num %v", i)) 122 } 123 } 124 125 // test struct{string,*TreeDelta} amino 126 func TestTreeDeltaImpAmino(t *testing.T) { testTreeDeltaImpAmino(t) } 127 func testTreeDeltaImpAmino(t *testing.T) { 128 for i, tdm := range testTreeDeltaMap { 129 // each tree delta 130 for k, td := range tdm { 131 imp := &TreeDeltaMapImp{Key: k, TreeValue: td} 132 133 expect, err := cdc.MarshalBinaryBare(imp) 134 require.NoError(t, err, fmt.Sprintf("num %v", i)) 135 136 actual, err := imp.MarshalToAmino(cdc) 137 require.NoError(t, err, fmt.Sprintf("num %v", i)) 138 require.EqualValues(t, expect, actual, fmt.Sprintf("num %v", i)) 139 140 var expectValue TreeDeltaMapImp 141 err = cdc.UnmarshalBinaryBare(expect, &expectValue) 142 require.NoError(t, err, fmt.Sprintf("num %v", i)) 143 144 var actualValue TreeDeltaMapImp 145 err = actualValue.UnmarshalFromAmino(cdc, expect) 146 require.NoError(t, err, fmt.Sprintf("num %v", i)) 147 require.EqualValues(t, expectValue, actualValue, fmt.Sprintf("num %v", i)) 148 } 149 } 150 } 151 152 // test TreeDelta amino 153 func TestTreeDeltaAmino(t *testing.T) { testTreeDeltaAmino(t) } 154 func testTreeDeltaAmino(t *testing.T) { 155 testTreeDeltas := []*TreeDelta{ 156 {}, 157 {nil, nil, nil}, 158 {[]*NodeJsonImp{}, []*NodeJson{}, []*CommitOrphansImp{}}, 159 { 160 []*NodeJsonImp{nil, {}, {"0x01", &NodeJson{Version: 1}}}, 161 []*NodeJson{nil, {}, {Version: 2}}, 162 []*CommitOrphansImp{nil, {}, {"0x01", 1}}, 163 }, 164 } 165 for i, td := range testTreeDeltas { 166 expect, err := cdc.MarshalBinaryBare(td) 167 require.NoError(t, err, fmt.Sprintf("num %v", i)) 168 169 actual, err := td.MarshalToAmino(cdc) 170 require.NoError(t, err, fmt.Sprintf("num %v", i)) 171 require.EqualValues(t, expect, actual, fmt.Sprintf("num %v", i)) 172 173 expectValue := TreeDelta{} 174 err = cdc.UnmarshalBinaryBare(expect, &expectValue) 175 require.NoError(t, err, fmt.Sprintf("num %v", i)) 176 177 actualValue := TreeDelta{} 178 err = actualValue.UnmarshalFromAmino(cdc, expect) 179 require.NoError(t, err, fmt.Sprintf("num %v", i)) 180 require.EqualValues(t, expectValue, actualValue, fmt.Sprintf("num %v", i)) 181 } 182 } 183 184 // test NodeJsonImp amino 185 func TestNodeJsonImpAmino(t *testing.T) { testNodeJsonImpAmino(t) } 186 func testNodeJsonImpAmino(t *testing.T) { 187 testNodeJsomImps := []*NodeJsonImp{ 188 {}, 189 {"0x01", nil}, 190 {"0x02", &NodeJson{}}, 191 {"0x03", &NodeJson{Version: 1}}, 192 } 193 194 for i, ni := range testNodeJsomImps { 195 expect, err := cdc.MarshalBinaryBare(ni) 196 require.NoError(t, err, fmt.Sprintf("num %v", i)) 197 198 actual, err := ni.MarshalToAmino(cdc) 199 require.NoError(t, err, fmt.Sprintf("num %v", i)) 200 require.EqualValues(t, expect, actual, fmt.Sprintf("num %v", i)) 201 202 expectValue := NodeJsonImp{} 203 err = cdc.UnmarshalBinaryBare(expect, &expectValue) 204 require.NoError(t, err, fmt.Sprintf("num %v", i)) 205 206 actualValue := NodeJsonImp{} 207 err = actualValue.UnmarshalFromAmino(cdc, expect) 208 require.NoError(t, err, fmt.Sprintf("num %v", i)) 209 require.EqualValues(t, expectValue, actualValue, fmt.Sprintf("num %v", i)) 210 211 } 212 } 213 214 // test CommitOrphansImp amino 215 func TestCommitOrphansImpAmino(t *testing.T) { testCommitOrphansImpAmino(t) } 216 func testCommitOrphansImpAmino(t *testing.T) { 217 testCommitOrphansImps := []*CommitOrphansImp{ 218 {}, 219 {"0x01", -1}, 220 {"0x01", math.MinInt64}, 221 {"0x01", math.MaxInt64}, 222 {"0x01", 1}, 223 } 224 225 for i, ci := range testCommitOrphansImps { 226 expect, err := cdc.MarshalBinaryBare(ci) 227 require.NoError(t, err, fmt.Sprintf("num %v", i)) 228 229 actual, err := ci.MarshalToAmino(cdc) 230 require.NoError(t, err, fmt.Sprintf("num %v", i)) 231 require.EqualValues(t, expect, actual, fmt.Sprintf("num %v", i)) 232 233 expectValue := CommitOrphansImp{} 234 err = cdc.UnmarshalBinaryBare(expect, &expectValue) 235 require.NoError(t, err, fmt.Sprintf("num %v", i)) 236 237 actualValue := CommitOrphansImp{} 238 err = actualValue.UnmarshalFromAmino(cdc, expect) 239 require.NoError(t, err, fmt.Sprintf("num %v", i)) 240 require.EqualValues(t, expectValue, actualValue, fmt.Sprintf("num %v", i)) 241 } 242 } 243 244 // test NodeJson amino 245 func TestNodeJsonAmino(t *testing.T) { testNodeJsonAmino(t) } 246 func testNodeJsonAmino(t *testing.T) { 247 testNodeJsons := []*NodeJson{ 248 {}, 249 {Key: []byte("0x01"), Value: []byte("0xff"), Hash: []byte("0xFF"), LeftHash: []byte("01"), RightHash: []byte("")}, 250 {Version: -1, Size: 1}, 251 {Version: math.MinInt64, Size: math.MaxInt64}, 252 {Height: int8(1)}, 253 {Height: int8(-1)}, 254 {Height: math.MaxInt8}, 255 {Height: math.MaxInt8}, 256 {Persisted: true, PrePersisted: false}, 257 {Key: []byte("0x01"), Value: []byte("0x02"), Hash: []byte("0x03"), LeftHash: []byte("0x04"), RightHash: []byte("0x05"), 258 Version: 1, Size: 1, Height: 1, Persisted: true, PrePersisted: true}, 259 } 260 261 for i, nj := range testNodeJsons { 262 expect, err := cdc.MarshalBinaryBare(nj) 263 require.NoError(t, err, fmt.Sprintf("num %v", i)) 264 265 actual, err := nj.MarshalToAmino(cdc) 266 require.NoError(t, err, fmt.Sprintf("num %v", i)) 267 require.EqualValues(t, expect, actual, fmt.Sprintf("num %v", i)) 268 269 expectValue := NodeJson{} 270 err = cdc.UnmarshalBinaryBare(expect, &expectValue) 271 require.NoError(t, err, fmt.Sprintf("num %v", i)) 272 273 actualValue := NodeJson{} 274 err = actualValue.UnmarshalFromAmino(cdc, expect) 275 require.NoError(t, err, fmt.Sprintf("num %v", i)) 276 require.EqualValues(t, expectValue, actualValue, fmt.Sprintf("num %v", i)) 277 } 278 } 279 280 // benchmark encode performance 281 func BenchmarkAminoEncodeDelta(b *testing.B) { benchmarkEncodeDelta(b, newEncoder("amino")) } 282 283 func BenchmarkJsonEncodeDelta(b *testing.B) { benchmarkEncodeDelta(b, newEncoder("json")) } 284 func benchmarkEncodeDelta(b *testing.B, enc encoder) { 285 data := newTestTreeDeltaMap() 286 287 b.ReportAllocs() 288 b.ResetTimer() 289 for i := 0; i < b.N; i++ { 290 enc.encodeFunc(data) 291 } 292 293 } 294 295 // benchmark decode performance 296 func BenchmarkAminoDecodeDelta(b *testing.B) { benchmarkDecodeDelta(b, newEncoder("amino")) } 297 298 func BenchmarkJsonDecodeDelta(b *testing.B) { benchmarkDecodeDelta(b, newEncoder("json")) } 299 func benchmarkDecodeDelta(b *testing.B, enc encoder) { 300 deltaList1 := newTestTreeDeltaMap() 301 data, _ := enc.encodeFunc(deltaList1) 302 303 b.ReportAllocs() 304 b.ResetTimer() 305 for i := 0; i < b.N; i++ { 306 enc.decodeFunc(data) 307 } 308 } 309 310 type encoder interface { 311 name() string 312 encodeFunc(TreeDeltaMap) ([]byte, error) 313 decodeFunc([]byte) (TreeDeltaMap, error) 314 } 315 316 func newEncoder(encType string) encoder { 317 switch encType { 318 case "amino": 319 return &aminoEncoder{} 320 case "json": 321 return &jsonEncoder{} 322 default: 323 } 324 panic("unsupport encoder") 325 } 326 327 // amino encoder 328 type aminoEncoder struct{} 329 330 func (ae *aminoEncoder) name() string { return "amino" } 331 func (ae *aminoEncoder) encodeFunc(data TreeDeltaMap) ([]byte, error) { 332 return data.MarshalToAmino(nil) 333 } 334 func (ae *aminoEncoder) decodeFunc(data []byte) (TreeDeltaMap, error) { 335 deltaList := TreeDeltaMap{} 336 err := deltaList.UnmarshalFromAmino(nil, data) 337 return deltaList, err 338 } 339 340 // json encoder 341 type jsonEncoder struct{} 342 343 func (je *jsonEncoder) name() string { return "json" } 344 func (je *jsonEncoder) encodeFunc(data TreeDeltaMap) ([]byte, error) { 345 return types.Json.Marshal(data) 346 } 347 func (je *jsonEncoder) decodeFunc(data []byte) (TreeDeltaMap, error) { 348 deltaList := TreeDeltaMap{} 349 err := types.Json.Unmarshal(data, &deltaList) 350 return deltaList, err 351 }