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