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