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  }