arnaucube
arnaucube/hermez-nodePublic Self-hosted repository
hermez-node/api/batch_test.go
api/batch_test.goRaw
  1package api
  2
  3import (
  4	"fmt"
  5	"strconv"
  6	"testing"
  7	"time"
  8
  9	ethCommon "github.com/ethereum/go-ethereum/common"
 10	"github.com/hermeznetwork/hermez-node/common"
 11	"github.com/hermeznetwork/hermez-node/db"
 12	"github.com/hermeznetwork/hermez-node/db/historydb"
 13	"github.com/mitchellh/copystructure"
 14	"github.com/stretchr/testify/assert"
 15)
 16
 17type testBatch struct {
 18	ItemID        int                       `json:"itemId"`
 19	BatchNum      common.BatchNum           `json:"batchNum"`
 20	EthBlockNum   int64                     `json:"ethereumBlockNum"`
 21	EthBlockHash  ethCommon.Hash            `json:"ethereumBlockHash"`
 22	Timestamp     time.Time                 `json:"timestamp"`
 23	ForgerAddr    ethCommon.Address         `json:"forgerAddr"`
 24	CollectedFees map[common.TokenID]string `json:"collectedFees"`
 25	TotalFeesUSD  *float64                  `json:"historicTotalCollectedFeesUSD"`
 26	StateRoot     string                    `json:"stateRoot"`
 27	NumAccounts   int                       `json:"numAccounts"`
 28	ExitRoot      string                    `json:"exitRoot"`
 29	ForgeL1TxsNum *int64                    `json:"forgeL1TransactionsNum"`
 30	SlotNum       int64                     `json:"slotNum"`
 31}
 32type testBatchesResponse struct {
 33	Batches    []testBatch    `json:"batches"`
 34	Pagination *db.Pagination `json:"pagination"`
 35}
 36
 37func (t testBatchesResponse) GetPagination() *db.Pagination {
 38	if t.Batches[0].ItemID < t.Batches[len(t.Batches)-1].ItemID {
 39		t.Pagination.FirstReturnedItem = t.Batches[0].ItemID
 40		t.Pagination.LastReturnedItem = t.Batches[len(t.Batches)-1].ItemID
 41	} else {
 42		t.Pagination.LastReturnedItem = t.Batches[0].ItemID
 43		t.Pagination.FirstReturnedItem = t.Batches[len(t.Batches)-1].ItemID
 44	}
 45	return t.Pagination
 46}
 47
 48func (t testBatchesResponse) Len() int {
 49	return len(t.Batches)
 50}
 51
 52func genTestBatches(blocks []common.Block, cBatches []common.Batch) []testBatch {
 53	tBatches := []testBatch{}
 54	for _, cBatch := range cBatches {
 55		block := common.Block{}
 56		found := false
 57		for _, b := range blocks {
 58			if b.EthBlockNum == cBatch.EthBlockNum {
 59				block = b
 60				found = true
 61				break
 62			}
 63		}
 64		if !found {
 65			panic("block not found")
 66		}
 67		collectedFees := make(map[common.TokenID]string)
 68		for k, v := range cBatch.CollectedFees {
 69			collectedFees[k] = v.String()
 70		}
 71		tBatch := testBatch{
 72			BatchNum:      cBatch.BatchNum,
 73			EthBlockNum:   cBatch.EthBlockNum,
 74			EthBlockHash:  block.Hash,
 75			Timestamp:     block.Timestamp,
 76			ForgerAddr:    cBatch.ForgerAddr,
 77			CollectedFees: collectedFees,
 78			TotalFeesUSD:  cBatch.TotalFeesUSD,
 79			StateRoot:     cBatch.StateRoot.String(),
 80			NumAccounts:   cBatch.NumAccounts,
 81			ExitRoot:      cBatch.ExitRoot.String(),
 82			ForgeL1TxsNum: cBatch.ForgeL1TxsNum,
 83			SlotNum:       cBatch.SlotNum,
 84		}
 85		tBatches = append(tBatches, tBatch)
 86	}
 87	return tBatches
 88}
 89
 90func TestGetBatches(t *testing.T) {
 91	endpoint := apiURL + "batches"
 92	fetchedBatches := []testBatch{}
 93	appendIter := func(intr interface{}) {
 94		for i := 0; i < len(intr.(*testBatchesResponse).Batches); i++ {
 95			tmp, err := copystructure.Copy(intr.(*testBatchesResponse).Batches[i])
 96			if err != nil {
 97				panic(err)
 98			}
 99			fetchedBatches = append(fetchedBatches, tmp.(testBatch))
100		}
101	}
102	// Get all (no filters)
103	limit := 3
104	path := fmt.Sprintf("%s?limit=%d&fromItem=", endpoint, limit)
105	err := doGoodReqPaginated(path, historydb.OrderAsc, &testBatchesResponse{}, appendIter)
106	assert.NoError(t, err)
107	assertBatches(t, tc.batches, fetchedBatches)
108
109	// minBatchNum
110	fetchedBatches = []testBatch{}
111	limit = 2
112	minBatchNum := tc.batches[len(tc.batches)/2].BatchNum
113	path = fmt.Sprintf("%s?minBatchNum=%d&limit=%d&fromItem=", endpoint, minBatchNum, limit)
114	err = doGoodReqPaginated(path, historydb.OrderAsc, &testBatchesResponse{}, appendIter)
115	assert.NoError(t, err)
116	minBatchNumBatches := []testBatch{}
117	for i := 0; i < len(tc.batches); i++ {
118		if tc.batches[i].BatchNum > minBatchNum {
119			minBatchNumBatches = append(minBatchNumBatches, tc.batches[i])
120		}
121	}
122	assertBatches(t, minBatchNumBatches, fetchedBatches)
123
124	// maxBatchNum
125	fetchedBatches = []testBatch{}
126	limit = 1
127	maxBatchNum := tc.batches[len(tc.batches)/2].BatchNum
128	path = fmt.Sprintf("%s?maxBatchNum=%d&limit=%d&fromItem=", endpoint, maxBatchNum, limit)
129	err = doGoodReqPaginated(path, historydb.OrderAsc, &testBatchesResponse{}, appendIter)
130	assert.NoError(t, err)
131	maxBatchNumBatches := []testBatch{}
132	for i := 0; i < len(tc.batches); i++ {
133		if tc.batches[i].BatchNum < maxBatchNum {
134			maxBatchNumBatches = append(maxBatchNumBatches, tc.batches[i])
135		}
136	}
137	assertBatches(t, maxBatchNumBatches, fetchedBatches)
138
139	// slotNum
140	fetchedBatches = []testBatch{}
141	limit = 5
142	slotNum := tc.batches[len(tc.batches)/2].SlotNum
143	path = fmt.Sprintf("%s?slotNum=%d&limit=%d&fromItem=", endpoint, slotNum, limit)
144	err = doGoodReqPaginated(path, historydb.OrderAsc, &testBatchesResponse{}, appendIter)
145	assert.NoError(t, err)
146	slotNumBatches := []testBatch{}
147	for i := 0; i < len(tc.batches); i++ {
148		if tc.batches[i].SlotNum == slotNum {
149			slotNumBatches = append(slotNumBatches, tc.batches[i])
150		}
151	}
152	assertBatches(t, slotNumBatches, fetchedBatches)
153
154	// forgerAddr
155	fetchedBatches = []testBatch{}
156	limit = 10
157	forgerAddr := tc.batches[len(tc.batches)/2].ForgerAddr
158	path = fmt.Sprintf("%s?forgerAddr=%s&limit=%d&fromItem=", endpoint, forgerAddr.String(), limit)
159	err = doGoodReqPaginated(path, historydb.OrderAsc, &testBatchesResponse{}, appendIter)
160	assert.NoError(t, err)
161	forgerAddrBatches := []testBatch{}
162	for i := 0; i < len(tc.batches); i++ {
163		if tc.batches[i].ForgerAddr == forgerAddr {
164			forgerAddrBatches = append(forgerAddrBatches, tc.batches[i])
165		}
166	}
167	assertBatches(t, forgerAddrBatches, fetchedBatches)
168
169	// All, in reverse order
170	fetchedBatches = []testBatch{}
171	limit = 6
172	path = fmt.Sprintf("%s?limit=%d&fromItem=", endpoint, limit)
173	err = doGoodReqPaginated(path, historydb.OrderDesc, &testBatchesResponse{}, appendIter)
174	assert.NoError(t, err)
175	flippedBatches := []testBatch{}
176	for i := len(tc.batches) - 1; i >= 0; i-- {
177		flippedBatches = append(flippedBatches, tc.batches[i])
178	}
179	assertBatches(t, flippedBatches, fetchedBatches)
180
181	// Mixed filters
182	fetchedBatches = []testBatch{}
183	limit = 1
184	maxBatchNum = tc.batches[len(tc.batches)-len(tc.batches)/4].BatchNum
185	minBatchNum = tc.batches[len(tc.batches)/4].BatchNum
186	path = fmt.Sprintf("%s?minBatchNum=%d&maxBatchNum=%d&limit=%d&fromItem=", endpoint, minBatchNum, maxBatchNum, limit)
187	err = doGoodReqPaginated(path, historydb.OrderAsc, &testBatchesResponse{}, appendIter)
188	assert.NoError(t, err)
189	minMaxBatchNumBatches := []testBatch{}
190	for i := 0; i < len(tc.batches); i++ {
191		if tc.batches[i].BatchNum < maxBatchNum && tc.batches[i].BatchNum > minBatchNum {
192			minMaxBatchNumBatches = append(minMaxBatchNumBatches, tc.batches[i])
193		}
194	}
195	assertBatches(t, minMaxBatchNumBatches, fetchedBatches)
196
197	// 400
198	// Invalid minBatchNum
199	path = fmt.Sprintf("%s?minBatchNum=%d", endpoint, -2)
200	err = doBadReq("GET", path, nil, 400)
201	assert.NoError(t, err)
202	// Invalid forgerAddr
203	path = fmt.Sprintf("%s?forgerAddr=%s", endpoint, "0xG0000001")
204	err = doBadReq("GET", path, nil, 400)
205	assert.NoError(t, err)
206	// 404
207	path = fmt.Sprintf("%s?slotNum=%d&minBatchNum=%d", endpoint, 1, 25)
208	err = doBadReq("GET", path, nil, 404)
209	assert.NoError(t, err)
210}
211
212func TestGetBatch(t *testing.T) {
213	endpoint := apiURL + "batches/"
214	for _, batch := range tc.batches {
215		fetchedBatch := testBatch{}
216		assert.NoError(
217			t, doGoodReq(
218				"GET",
219				endpoint+strconv.Itoa(int(batch.BatchNum)),
220				nil, &fetchedBatch,
221			),
222		)
223		assertBatch(t, batch, fetchedBatch)
224	}
225	// 400
226	assert.NoError(t, doBadReq("GET", endpoint+"foo", nil, 400))
227	// 404
228	assert.NoError(t, doBadReq("GET", endpoint+"99999", nil, 404))
229}
230
231func assertBatches(t *testing.T, expected, actual []testBatch) {
232	assert.Equal(t, len(expected), len(actual))
233	for i := 0; i < len(expected); i++ {
234		assertBatch(t, expected[i], actual[i])
235	}
236}
237
238func assertBatch(t *testing.T, expected, actual testBatch) {
239	assert.Equal(t, expected.Timestamp.Unix(), actual.Timestamp.Unix())
240	expected.Timestamp = actual.Timestamp
241	actual.ItemID = expected.ItemID
242	assert.Equal(t, expected, actual)
243}