hermez-node/api/bids_test.go
api/bids_test.goRaw
1package api
2
3import (
4 "fmt"
5 "testing"
6 "time"
7
8 ethCommon "github.com/ethereum/go-ethereum/common"
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 testBid struct {
17 ItemID uint64 `json:"itemId"`
18 SlotNum int64 `json:"slotNum"`
19 BidValue string `json:"bidValue"`
20 EthBlockNum int64 `json:"ethereumBlockNum"`
21 Bidder ethCommon.Address `json:"bidderAddr"`
22 Forger ethCommon.Address `json:"forgerAddr"`
23 URL string `json:"URL"`
24 Timestamp time.Time `json:"timestamp"`
25}
26
27type testBidsResponse struct {
28 Bids []testBid `json:"bids"`
29 Pagination *db.Pagination `json:"pagination"`
30}
31
32func (t testBidsResponse) GetPagination() *db.Pagination {
33 if t.Bids[0].ItemID < t.Bids[len(t.Bids)-1].ItemID {
34 t.Pagination.FirstReturnedItem = t.Bids[0].ItemID
35 t.Pagination.LastReturnedItem = t.Bids[len(t.Bids)-1].ItemID
36 } else {
37 t.Pagination.LastReturnedItem = t.Bids[0].ItemID
38 t.Pagination.FirstReturnedItem = t.Bids[len(t.Bids)-1].ItemID
39 }
40 return t.Pagination
41}
42
43func (t testBidsResponse) Len() int {
44 return len(t.Bids)
45}
46
47func genTestBids(blocks []common.Block, coordinators []historydb.CoordinatorAPI, bids []common.Bid) []testBid {
48 tBids := []testBid{}
49 for _, bid := range bids {
50 block := getBlockByNum(bid.EthBlockNum, blocks)
51 coordinator := getCoordinatorByBidder(bid.Bidder, coordinators)
52 tBid := testBid{
53 SlotNum: bid.SlotNum,
54 BidValue: bid.BidValue.String(),
55 EthBlockNum: bid.EthBlockNum,
56 Bidder: bid.Bidder,
57 Forger: coordinator.Forger,
58 URL: coordinator.URL,
59 Timestamp: block.Timestamp,
60 }
61 tBids = append(tBids, tBid)
62 }
63 return tBids
64}
65
66func TestGetBids(t *testing.T) {
67 endpoint := apiURL + "bids"
68 fetchedBids := []testBid{}
69 appendIter := func(intr interface{}) {
70 for i := 0; i < len(intr.(*testBidsResponse).Bids); i++ {
71 tmp, err := copystructure.Copy(intr.(*testBidsResponse).Bids[i])
72 if err != nil {
73 panic(err)
74 }
75 fetchedBids = append(fetchedBids, tmp.(testBid))
76 }
77 }
78
79 limit := 3
80 // bidderAddress
81 fetchedBids = []testBid{}
82 bidderAddress := tc.bids[3].Bidder
83 path := fmt.Sprintf("%s?bidderAddr=%s&limit=%d&fromItem=", endpoint, bidderAddress.String(), limit)
84 err := doGoodReqPaginated(path, historydb.OrderAsc, &testBidsResponse{}, appendIter)
85 assert.NoError(t, err)
86 bidderAddrBids := []testBid{}
87 for i := 0; i < len(tc.bids); i++ {
88 if tc.bids[i].Bidder == bidderAddress {
89 bidderAddrBids = append(bidderAddrBids, tc.bids[i])
90 }
91 }
92 assertBids(t, bidderAddrBids, fetchedBids)
93
94 // slotNum
95 fetchedBids = []testBid{}
96 slotNum := tc.bids[3].SlotNum
97 path = fmt.Sprintf("%s?slotNum=%d&limit=%d&fromItem=", endpoint, slotNum, limit)
98 err = doGoodReqPaginated(path, historydb.OrderAsc, &testBidsResponse{}, appendIter)
99 assert.NoError(t, err)
100 slotNumBids := []testBid{}
101 for i := 0; i < len(tc.bids); i++ {
102 if tc.bids[i].SlotNum == slotNum {
103 slotNumBids = append(slotNumBids, tc.bids[i])
104 }
105 }
106 assertBids(t, slotNumBids, fetchedBids)
107
108 // slotNum, in reverse order
109 fetchedBids = []testBid{}
110 path = fmt.Sprintf("%s?slotNum=%d&limit=%d&fromItem=", endpoint, slotNum, limit)
111 err = doGoodReqPaginated(path, historydb.OrderDesc, &testBidsResponse{}, appendIter)
112 assert.NoError(t, err)
113 flippedBids := []testBid{}
114 for i := len(slotNumBids) - 1; i >= 0; i-- {
115 flippedBids = append(flippedBids, slotNumBids[i])
116 }
117 assertBids(t, flippedBids, fetchedBids)
118
119 // Mixed filters
120 fetchedBids = []testBid{}
121 bidderAddress = tc.bids[9].Bidder
122 slotNum = tc.bids[4].SlotNum
123 path = fmt.Sprintf("%s?bidderAddr=%s&slotNum=%d&limit=%d&fromItem=", endpoint, bidderAddress.String(), slotNum, limit)
124 err = doGoodReqPaginated(path, historydb.OrderAsc, &testBidsResponse{}, appendIter)
125 assert.NoError(t, err)
126 slotNumBidderAddrBids := []testBid{}
127 for i := 0; i < len(tc.bids); i++ {
128 if tc.bids[i].Bidder == bidderAddress && tc.bids[i].SlotNum == slotNum {
129 slotNumBidderAddrBids = append(slotNumBidderAddrBids, tc.bids[i])
130 }
131 }
132 assertBids(t, slotNumBidderAddrBids, fetchedBids)
133
134 // 400
135 // No filters
136 path = fmt.Sprintf("%s?limit=%d&fromItem=", endpoint, limit)
137 err = doBadReq("GET", path, nil, 400)
138 assert.NoError(t, err)
139 // Invalid slotNum
140 path = fmt.Sprintf("%s?slotNum=%d", endpoint, -2)
141 err = doBadReq("GET", path, nil, 400)
142 assert.NoError(t, err)
143 // Invalid bidderAddress
144 path = fmt.Sprintf("%s?bidderAddr=%s", endpoint, "0xG0000001")
145 err = doBadReq("GET", path, nil, 400)
146 assert.NoError(t, err)
147 // 404
148 path = fmt.Sprintf("%s?slotNum=%d&bidderAddr=%s", endpoint, tc.bids[0].SlotNum, tc.bids[1].Bidder.String())
149 err = doBadReq("GET", path, nil, 404)
150 assert.NoError(t, err)
151}
152
153func assertBids(t *testing.T, expected, actual []testBid) {
154 assert.Equal(t, len(expected), len(actual))
155 for i := 0; i < len(expected); i++ {
156 assertBid(t, expected[i], actual[i])
157 }
158}
159
160func assertBid(t *testing.T, expected, actual testBid) {
161 assert.Equal(t, expected.Timestamp.Unix(), actual.Timestamp.Unix())
162 expected.Timestamp = actual.Timestamp
163 actual.ItemID = expected.ItemID
164 assert.Equal(t, expected, actual)
165}