arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/api/account_test.go
api/account_test.goRaw
  1package api
  2
  3import (
  4	"fmt"
  5	"strconv"
  6	"testing"
  7
  8	"github.com/hermeznetwork/hermez-node/apitypes"
  9	"github.com/hermeznetwork/hermez-node/common"
 10	"github.com/hermeznetwork/hermez-node/db/historydb"
 11	"github.com/mitchellh/copystructure"
 12	"github.com/stretchr/testify/assert"
 13	"github.com/stretchr/testify/require"
 14)
 15
 16type testAccount struct {
 17	ItemID    uint64                 `json:"itemId"`
 18	Idx       apitypes.HezIdx        `json:"accountIndex"`
 19	BatchNum  common.BatchNum        `json:"batchNum"`
 20	PublicKey apitypes.HezBJJ        `json:"bjj"`
 21	EthAddr   apitypes.HezEthAddr    `json:"hezEthereumAddress"`
 22	Nonce     common.Nonce           `json:"nonce"`
 23	Balance   *apitypes.BigIntStr    `json:"balance"`
 24	Token     historydb.TokenWithUSD `json:"token"`
 25}
 26
 27type testAccountsResponse struct {
 28	Accounts     []testAccount `json:"accounts"`
 29	PendingItems uint64        `json:"pendingItems"`
 30}
 31
 32func (t testAccountsResponse) GetPending() (pendingItems, lastItemID uint64) {
 33	pendingItems = t.PendingItems
 34	lastItemID = t.Accounts[len(t.Accounts)-1].ItemID
 35	return pendingItems, lastItemID
 36}
 37
 38func (t *testAccountsResponse) Len() int { return len(t.Accounts) }
 39
 40func (t testAccountsResponse) New() Pendinger { return &testAccountsResponse{} }
 41
 42func genTestAccounts(accounts []common.Account, tokens []historydb.TokenWithUSD) []testAccount {
 43	tAccounts := []testAccount{}
 44	for x, account := range accounts {
 45		token := getTokenByID(account.TokenID, tokens)
 46		tAccount := testAccount{
 47			ItemID:    uint64(x + 1),
 48			Idx:       apitypes.HezIdx(idxToHez(account.Idx, token.Symbol)),
 49			PublicKey: apitypes.NewHezBJJ(account.BJJ),
 50			EthAddr:   apitypes.NewHezEthAddr(account.EthAddr),
 51			Nonce:     account.Nonce,
 52			Balance:   apitypes.NewBigIntStr(account.Balance),
 53			Token:     token,
 54		}
 55		tAccounts = append(tAccounts, tAccount)
 56	}
 57	return tAccounts
 58}
 59
 60func TestGetAccounts(t *testing.T) {
 61	endpoint := apiURL + "accounts"
 62	fetchedAccounts := []testAccount{}
 63
 64	appendIter := func(intr interface{}) {
 65		for i := 0; i < len(intr.(*testAccountsResponse).Accounts); i++ {
 66			tmp, err := copystructure.Copy(intr.(*testAccountsResponse).Accounts[i])
 67			if err != nil {
 68				panic(err)
 69			}
 70			fetchedAccounts = append(fetchedAccounts, tmp.(testAccount))
 71		}
 72	}
 73
 74	limit := 5
 75	stringIds := strconv.Itoa(int(tc.tokens[2].TokenID)) + "," + strconv.Itoa(int(tc.tokens[5].TokenID)) + "," + strconv.Itoa(int(tc.tokens[6].TokenID))
 76
 77	// Filter by BJJ
 78	path := fmt.Sprintf("%s?BJJ=%s&limit=%d", endpoint, tc.accounts[0].PublicKey, limit)
 79	err := doGoodReqPaginated(path, historydb.OrderAsc, &testAccountsResponse{}, appendIter)
 80	require.NoError(t, err)
 81	assert.Greater(t, len(fetchedAccounts), 0)
 82	assert.LessOrEqual(t, len(fetchedAccounts), len(tc.accounts))
 83	fetchedAccounts = []testAccount{}
 84	// Filter by ethAddr
 85	path = fmt.Sprintf("%s?hezEthereumAddress=%s&limit=%d", endpoint, tc.accounts[3].EthAddr, limit)
 86	err = doGoodReqPaginated(path, historydb.OrderAsc, &testAccountsResponse{}, appendIter)
 87	require.NoError(t, err)
 88	assert.Greater(t, len(fetchedAccounts), 0)
 89	assert.LessOrEqual(t, len(fetchedAccounts), len(tc.accounts))
 90	fetchedAccounts = []testAccount{}
 91	// both filters (incompatible)
 92	path = fmt.Sprintf("%s?hezEthereumAddress=%s&BJJ=%s&limit=%d", endpoint, tc.accounts[0].EthAddr, tc.accounts[0].PublicKey, limit)
 93	err = doBadReq("GET", path, nil, 400)
 94	require.NoError(t, err)
 95	fetchedAccounts = []testAccount{}
 96	// Filter by token IDs
 97	path = fmt.Sprintf("%s?tokenIds=%s&limit=%d", endpoint, stringIds, limit)
 98	err = doGoodReqPaginated(path, historydb.OrderAsc, &testAccountsResponse{}, appendIter)
 99	require.NoError(t, err)
100	assert.Greater(t, len(fetchedAccounts), 0)
101	assert.LessOrEqual(t, len(fetchedAccounts), len(tc.accounts))
102	fetchedAccounts = []testAccount{}
103	// Token Ids + bjj
104	path = fmt.Sprintf("%s?tokenIds=%s&BJJ=%s&limit=%d", endpoint, stringIds, tc.accounts[10].PublicKey, limit)
105	err = doGoodReqPaginated(path, historydb.OrderAsc, &testAccountsResponse{}, appendIter)
106	require.NoError(t, err)
107	assert.Greater(t, len(fetchedAccounts), 0)
108	assert.LessOrEqual(t, len(fetchedAccounts), len(tc.accounts))
109	fetchedAccounts = []testAccount{}
110	// No filters (checks response content)
111	path = fmt.Sprintf("%s?limit=%d", endpoint, limit)
112	err = doGoodReqPaginated(path, historydb.OrderAsc, &testAccountsResponse{}, appendIter)
113	require.NoError(t, err)
114	assert.Equal(t, len(tc.accounts), len(fetchedAccounts))
115	for i := 0; i < len(fetchedAccounts); i++ {
116		fetchedAccounts[i].Token.ItemID = 0
117		if tc.accounts[i].Token.USDUpdate != nil {
118			assert.Less(t, fetchedAccounts[i].Token.USDUpdate.Unix()-3, tc.accounts[i].Token.USDUpdate.Unix())
119			fetchedAccounts[i].Token.USDUpdate = tc.accounts[i].Token.USDUpdate
120		}
121		assert.Equal(t, tc.accounts[i], fetchedAccounts[i])
122	}
123
124	// No filters  Reverse Order (checks response content)
125	reversedAccounts := []testAccount{}
126	appendIter = func(intr interface{}) {
127		for i := 0; i < len(intr.(*testAccountsResponse).Accounts); i++ {
128			tmp, err := copystructure.Copy(intr.(*testAccountsResponse).Accounts[i])
129			if err != nil {
130				panic(err)
131			}
132			reversedAccounts = append(reversedAccounts, tmp.(testAccount))
133		}
134	}
135	err = doGoodReqPaginated(path, historydb.OrderDesc, &testAccountsResponse{}, appendIter)
136	require.NoError(t, err)
137	assert.Equal(t, len(reversedAccounts), len(fetchedAccounts))
138	for i := 0; i < len(fetchedAccounts); i++ {
139		reversedAccounts[i].Token.ItemID = 0
140		fetchedAccounts[len(fetchedAccounts)-1-i].Token.ItemID = 0
141		if reversedAccounts[i].Token.USDUpdate != nil {
142			assert.Less(t, fetchedAccounts[len(fetchedAccounts)-1-i].Token.USDUpdate.Unix()-3, reversedAccounts[i].Token.USDUpdate.Unix())
143			fetchedAccounts[len(fetchedAccounts)-1-i].Token.USDUpdate = reversedAccounts[i].Token.USDUpdate
144		}
145		assert.Equal(t, reversedAccounts[i], fetchedAccounts[len(fetchedAccounts)-1-i])
146	}
147
148	// 400
149	path = fmt.Sprintf("%s?hezEthereumAddress=hez:0x123456", endpoint)
150	err = doBadReq("GET", path, nil, 400)
151	require.NoError(t, err)
152
153	// Test GetAccount
154	path = fmt.Sprintf("%s/%s", endpoint, fetchedAccounts[2].Idx)
155	account := testAccount{}
156	require.NoError(t, doGoodReq("GET", path, nil, &account))
157	account.Token.ItemID = 0
158	assert.Equal(t, fetchedAccounts[2], account)
159
160	// 400
161	path = fmt.Sprintf("%s/hez:12345", endpoint)
162	err = doBadReq("GET", path, nil, 400)
163	require.NoError(t, err)
164	// 404
165	path = fmt.Sprintf("%s/hez:10:12345", endpoint)
166	err = doBadReq("GET", path, nil, 404)
167	require.NoError(t, err)
168}