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.PublicKey),
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?hermezEthereumAddress=%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?hermezEthereumAddress=%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 // Test GetAccount
148 path = fmt.Sprintf("%s/%s", endpoint, fetchedAccounts[2].Idx)
149 account := testAccount{}
150 assert.NoError(t, doGoodReq("GET", path, nil, &account))
151 account.Token.ItemID = 0
152 assert.Equal(t, fetchedAccounts[2], account)
153
154 // 400
155 path = fmt.Sprintf("%s/hez:12345", endpoint)
156 err = doBadReq("GET", path, nil, 400)
157 assert.NoError(t, err)
158 // 404
159 path = fmt.Sprintf("%s/hez:10:12345", endpoint)
160 err = doBadReq("GET", path, nil, 404)
161 assert.NoError(t, err)
162}