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