github.com/status-im/status-go@v1.1.0/services/wallet/history/balance_test.go (about)

     1  package history
     2  
     3  import (
     4  	"math/big"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/require"
     9  
    10  	"github.com/ethereum/go-ethereum/common"
    11  	"github.com/status-im/status-go/t/helpers"
    12  	"github.com/status-im/status-go/walletdatabase"
    13  )
    14  
    15  func newTestDB(t *testing.T) *BalanceDB {
    16  	db, err := helpers.SetupTestMemorySQLDB(walletdatabase.DbInitializer{})
    17  	require.NoError(t, err)
    18  	return NewBalanceDB(db)
    19  }
    20  
    21  func dbWithEntries(t *testing.T, entries []*entry) *BalanceDB {
    22  	db := newTestDB(t)
    23  	for _, entry := range entries {
    24  		err := db.add(entry)
    25  		require.NoError(t, err)
    26  	}
    27  	return db
    28  }
    29  
    30  func TestBalance_addPaddingPoints(t *testing.T) {
    31  	type args struct {
    32  		currency         string
    33  		addresses        []common.Address
    34  		fromTimestamp    uint64
    35  		currentTimestamp uint64
    36  		data             []*entry
    37  		limit            int
    38  	}
    39  	tests := []struct {
    40  		name    string
    41  		args    args
    42  		want    []*entry
    43  		wantErr bool
    44  	}{
    45  		{
    46  			name: "addOnePaddingPointAtMiddle",
    47  			args: args{
    48  				currency:         "ETH",
    49  				addresses:        []common.Address{common.Address{1}},
    50  				fromTimestamp:    0,
    51  				currentTimestamp: 2,
    52  				data: []*entry{
    53  					{
    54  						balance:     big.NewInt(0),
    55  						timestamp:   0,
    56  						tokenSymbol: "ETH",
    57  						address:     common.Address{1},
    58  					},
    59  					{
    60  						balance:     big.NewInt(2),
    61  						timestamp:   2,
    62  						tokenSymbol: "ETH",
    63  						address:     common.Address{1},
    64  					},
    65  				},
    66  				limit: 3,
    67  			},
    68  			want: []*entry{
    69  				{
    70  					balance:     big.NewInt(0),
    71  					timestamp:   0,
    72  					tokenSymbol: "ETH",
    73  					address:     common.Address{1},
    74  				},
    75  				{
    76  					balance:     big.NewInt(0),
    77  					timestamp:   1,
    78  					tokenSymbol: "ETH",
    79  					address:     common.Address{1},
    80  				},
    81  				{
    82  					balance:     big.NewInt(2),
    83  					timestamp:   2,
    84  					tokenSymbol: "ETH",
    85  					address:     common.Address{1},
    86  				},
    87  			},
    88  			wantErr: false,
    89  		},
    90  		{
    91  			name: "noPaddingEqualsLimit",
    92  			args: args{
    93  				currency:         "ETH",
    94  				addresses:        []common.Address{common.Address{1}},
    95  				fromTimestamp:    0,
    96  				currentTimestamp: 2,
    97  				data: []*entry{
    98  					{
    99  						balance:     big.NewInt(0),
   100  						timestamp:   0,
   101  						block:       big.NewInt(1),
   102  						tokenSymbol: "ETH",
   103  						address:     common.Address{1},
   104  					},
   105  					{
   106  						balance:     big.NewInt(1),
   107  						timestamp:   2,
   108  						block:       big.NewInt(2),
   109  						tokenSymbol: "ETH",
   110  						address:     common.Address{1},
   111  					},
   112  				},
   113  				limit: 2,
   114  			},
   115  			want: []*entry{
   116  				{
   117  					balance:     big.NewInt(0),
   118  					timestamp:   0,
   119  					block:       big.NewInt(1),
   120  					tokenSymbol: "ETH",
   121  					address:     common.Address{1},
   122  				},
   123  				{
   124  					balance:     big.NewInt(1),
   125  					timestamp:   2,
   126  					block:       big.NewInt(2),
   127  					tokenSymbol: "ETH",
   128  					address:     common.Address{1},
   129  				},
   130  			},
   131  			wantErr: false,
   132  		},
   133  		{
   134  			name: "limitLessThanDataSize",
   135  			args: args{
   136  				currency:         "ETH",
   137  				addresses:        []common.Address{common.Address{1}},
   138  				fromTimestamp:    0,
   139  				currentTimestamp: 2,
   140  				data: []*entry{
   141  					{
   142  						balance:     big.NewInt(0),
   143  						timestamp:   0,
   144  						block:       big.NewInt(1),
   145  						tokenSymbol: "ETH",
   146  						address:     common.Address{1},
   147  					},
   148  					{
   149  						balance:     big.NewInt(1),
   150  						timestamp:   2,
   151  						block:       big.NewInt(2),
   152  						tokenSymbol: "ETH",
   153  						address:     common.Address{1},
   154  					},
   155  				},
   156  				limit: 1,
   157  			},
   158  			want: []*entry{
   159  				{
   160  					balance:     big.NewInt(0),
   161  					timestamp:   0,
   162  					block:       big.NewInt(1),
   163  					tokenSymbol: "ETH",
   164  					address:     common.Address{1},
   165  				},
   166  				{
   167  					balance:     big.NewInt(1),
   168  					timestamp:   2,
   169  					block:       big.NewInt(2),
   170  					tokenSymbol: "ETH",
   171  					address:     common.Address{1},
   172  				},
   173  			},
   174  			wantErr: false,
   175  		},
   176  		{
   177  			name: "addMultiplePaddingPoints",
   178  			args: args{
   179  				currency:         "ETH",
   180  				addresses:        []common.Address{common.Address{1}},
   181  				fromTimestamp:    1,
   182  				currentTimestamp: 5,
   183  				data: []*entry{
   184  					{
   185  						balance:     big.NewInt(0),
   186  						timestamp:   1,
   187  						tokenSymbol: "ETH",
   188  						address:     common.Address{1},
   189  					},
   190  					{
   191  						balance:     big.NewInt(4),
   192  						timestamp:   4,
   193  						tokenSymbol: "ETH",
   194  						address:     common.Address{1},
   195  					},
   196  					{
   197  						balance:     big.NewInt(5),
   198  						timestamp:   5,
   199  						tokenSymbol: "ETH",
   200  						address:     common.Address{1},
   201  					},
   202  				},
   203  				limit: 5,
   204  			},
   205  			want: []*entry{
   206  				{
   207  					balance:     big.NewInt(0),
   208  					timestamp:   1,
   209  					tokenSymbol: "ETH",
   210  					address:     common.Address{1},
   211  				},
   212  				{
   213  					balance:     big.NewInt(0),
   214  					timestamp:   2,
   215  					tokenSymbol: "ETH",
   216  					address:     common.Address{1},
   217  				},
   218  				{
   219  					balance:     big.NewInt(0),
   220  					timestamp:   3,
   221  					tokenSymbol: "ETH",
   222  					address:     common.Address{1},
   223  				},
   224  				{
   225  					balance:     big.NewInt(4),
   226  					timestamp:   4,
   227  					tokenSymbol: "ETH",
   228  					address:     common.Address{1},
   229  				},
   230  				{
   231  					balance:     big.NewInt(5),
   232  					timestamp:   5,
   233  					tokenSymbol: "ETH",
   234  					address:     common.Address{1},
   235  				},
   236  			},
   237  			wantErr: false,
   238  		},
   239  		{
   240  			name: "addMultiplePaddingPointsDuplicateTimestamps",
   241  			args: args{
   242  				currency:         "ETH",
   243  				addresses:        []common.Address{common.Address{1}},
   244  				fromTimestamp:    1,
   245  				currentTimestamp: 5,
   246  				data: []*entry{
   247  					{
   248  						balance:     big.NewInt(0),
   249  						timestamp:   1,
   250  						tokenSymbol: "ETH",
   251  						address:     common.Address{1},
   252  					},
   253  					{
   254  						balance:     big.NewInt(0),
   255  						timestamp:   1,
   256  						tokenSymbol: "ETH",
   257  						address:     common.Address{1},
   258  					},
   259  					{
   260  						balance:     big.NewInt(4),
   261  						timestamp:   4,
   262  						tokenSymbol: "ETH",
   263  						address:     common.Address{1},
   264  					},
   265  					{
   266  						balance:     big.NewInt(5),
   267  						timestamp:   5,
   268  						tokenSymbol: "ETH",
   269  						address:     common.Address{1},
   270  					},
   271  				},
   272  				limit: 5,
   273  			},
   274  			want: []*entry{
   275  				{
   276  					balance:     big.NewInt(0),
   277  					timestamp:   1,
   278  					tokenSymbol: "ETH",
   279  					address:     common.Address{1},
   280  				},
   281  				{
   282  					balance:     big.NewInt(0),
   283  					timestamp:   1,
   284  					tokenSymbol: "ETH",
   285  					address:     common.Address{1},
   286  				},
   287  				{
   288  					balance:     big.NewInt(0),
   289  					timestamp:   2,
   290  					tokenSymbol: "ETH",
   291  					address:     common.Address{1},
   292  				},
   293  				{
   294  					balance:     big.NewInt(4),
   295  					timestamp:   4,
   296  					tokenSymbol: "ETH",
   297  					address:     common.Address{1},
   298  				},
   299  				{
   300  					balance:     big.NewInt(5),
   301  					timestamp:   5,
   302  					tokenSymbol: "ETH",
   303  					address:     common.Address{1},
   304  				},
   305  			},
   306  			wantErr: false,
   307  		},
   308  	}
   309  
   310  	for _, tt := range tests {
   311  		t.Run(tt.name, func(t *testing.T) {
   312  			gotRes, err := addPaddingPoints(tt.args.currency, tt.args.addresses, tt.args.currentTimestamp, tt.args.data, tt.args.limit)
   313  			if (err != nil) != tt.wantErr {
   314  				t.Errorf("Balance.addPaddingPoints() error = %v, wantErr %v", err, tt.wantErr)
   315  				return
   316  			}
   317  			if !reflect.DeepEqual(gotRes, tt.want) {
   318  				t.Errorf("Balance.addPaddingPoints() = %v, want %v", gotRes, tt.want)
   319  			}
   320  		})
   321  	}
   322  }
   323  
   324  func TestBalance_addEdgePoints(t *testing.T) {
   325  
   326  	walletDB := newTestDB(t)
   327  
   328  	type fields struct {
   329  		db *BalanceDB
   330  	}
   331  	type args struct {
   332  		chainID       uint64
   333  		currency      string
   334  		addresses     []common.Address
   335  		fromTimestamp uint64
   336  		toTimestamp   uint64
   337  		data          []*entry
   338  	}
   339  	tests := []struct {
   340  		name    string
   341  		fields  fields
   342  		args    args
   343  		wantRes []*entry
   344  		wantErr bool
   345  	}{
   346  		{
   347  			name: "addToEmptyData",
   348  			fields: fields{
   349  				db: walletDB,
   350  			},
   351  			args: args{
   352  				chainID:       111,
   353  				currency:      "SNT",
   354  				addresses:     []common.Address{common.Address{1}},
   355  				fromTimestamp: 1,
   356  				toTimestamp:   2,
   357  				data:          []*entry{},
   358  			},
   359  			wantRes: []*entry{
   360  				{
   361  					chainID:     111,
   362  					balance:     big.NewInt(0),
   363  					timestamp:   1,
   364  					tokenSymbol: "SNT",
   365  					address:     common.Address{1},
   366  				},
   367  				{
   368  					chainID:     111,
   369  					balance:     big.NewInt(0),
   370  					timestamp:   2,
   371  					tokenSymbol: "SNT",
   372  					address:     common.Address{1},
   373  				},
   374  			},
   375  			wantErr: false,
   376  		},
   377  		{
   378  			name: "addToEmptyDataSinceGenesis",
   379  			fields: fields{
   380  				db: walletDB,
   381  			},
   382  			args: args{
   383  				chainID:       111,
   384  				currency:      "SNT",
   385  				addresses:     []common.Address{common.Address{1}},
   386  				fromTimestamp: 0, // will set to genesisTimestamp
   387  				toTimestamp:   genesisTimestamp + 1,
   388  				data:          []*entry{},
   389  			},
   390  			wantRes: []*entry{
   391  				{
   392  					chainID:     111,
   393  					balance:     big.NewInt(0),
   394  					timestamp:   genesisTimestamp,
   395  					tokenSymbol: "SNT",
   396  					address:     common.Address{1},
   397  				},
   398  				{
   399  					chainID:     111,
   400  					balance:     big.NewInt(0),
   401  					timestamp:   genesisTimestamp + 1,
   402  					tokenSymbol: "SNT",
   403  					address:     common.Address{1},
   404  				},
   405  			},
   406  			wantErr: false,
   407  		},
   408  		{
   409  			name: "addToNonEmptyDataFromPreviousEntry",
   410  			fields: fields{
   411  				db: dbWithEntries(t, []*entry{
   412  					{
   413  						chainID:     111,
   414  						balance:     big.NewInt(1),
   415  						timestamp:   1,
   416  						block:       big.NewInt(1),
   417  						tokenSymbol: "SNT",
   418  						address:     common.Address{1},
   419  					},
   420  				}),
   421  			},
   422  			args: args{
   423  				chainID:       111,
   424  				currency:      "SNT",
   425  				addresses:     []common.Address{common.Address{1}},
   426  				fromTimestamp: 2,
   427  				toTimestamp:   4,
   428  				data: []*entry{
   429  					{
   430  						chainID:     111,
   431  						balance:     big.NewInt(3),
   432  						timestamp:   3,
   433  						block:       big.NewInt(3),
   434  						tokenSymbol: "SNT",
   435  						address:     common.Address{1},
   436  					},
   437  					{
   438  						chainID:     111,
   439  						balance:     big.NewInt(2),
   440  						timestamp:   4,
   441  						block:       big.NewInt(4),
   442  						tokenSymbol: "SNT",
   443  						address:     common.Address{1},
   444  					},
   445  				},
   446  			},
   447  			wantRes: []*entry{
   448  				{
   449  					chainID:     111,
   450  					balance:     big.NewInt(1),
   451  					timestamp:   2,
   452  					tokenSymbol: "SNT",
   453  					address:     common.Address{1},
   454  				},
   455  				{
   456  					chainID:     111,
   457  					balance:     big.NewInt(3),
   458  					timestamp:   3,
   459  					block:       big.NewInt(3),
   460  					tokenSymbol: "SNT",
   461  					address:     common.Address{1},
   462  				},
   463  				{
   464  					chainID:     111,
   465  					balance:     big.NewInt(2),
   466  					timestamp:   4,
   467  					block:       big.NewInt(4),
   468  					tokenSymbol: "SNT",
   469  					address:     common.Address{1},
   470  				},
   471  			},
   472  			wantErr: false,
   473  		},
   474  		{
   475  			name: "addToNonEmptyData",
   476  			fields: fields{
   477  				db: walletDB,
   478  			},
   479  			args: args{
   480  				chainID:       111,
   481  				currency:      "SNT",
   482  				addresses:     []common.Address{common.Address{1}},
   483  				fromTimestamp: 1,
   484  				toTimestamp:   2,
   485  				data: []*entry{
   486  					{
   487  						chainID:     111,
   488  						balance:     big.NewInt(2),
   489  						timestamp:   2,
   490  						block:       big.NewInt(2),
   491  						tokenSymbol: "SNT",
   492  						address:     common.Address{1},
   493  					},
   494  				},
   495  			},
   496  			wantRes: []*entry{
   497  				{
   498  					chainID:     111,
   499  					balance:     big.NewInt(0),
   500  					timestamp:   1,
   501  					tokenSymbol: "SNT",
   502  					address:     common.Address{1},
   503  				},
   504  				{
   505  					chainID:     111,
   506  					balance:     big.NewInt(2),
   507  					timestamp:   2,
   508  					block:       big.NewInt(2),
   509  					tokenSymbol: "SNT",
   510  					address:     common.Address{1},
   511  				},
   512  			},
   513  			wantErr: false,
   514  		},
   515  	}
   516  	for _, tt := range tests {
   517  		t.Run(tt.name, func(t *testing.T) {
   518  			b := &Balance{
   519  				db: tt.fields.db,
   520  			}
   521  			gotRes, err := b.addEdgePoints(tt.args.chainID, tt.args.currency, tt.args.addresses, tt.args.fromTimestamp, tt.args.toTimestamp, tt.args.data)
   522  			if (err != nil) != tt.wantErr {
   523  				t.Errorf("Balance.addEdgePoints() error = %v, wantErr %v", err, tt.wantErr)
   524  				return
   525  			}
   526  			if !reflect.DeepEqual(gotRes, tt.wantRes) {
   527  				t.Errorf("Balance.addEdgePoints() = \n%v,\nwant \n%v", gotRes, tt.wantRes)
   528  			}
   529  		})
   530  	}
   531  }