OSDN Git Service

1ac993acbc6c149d26f5aa392949eb6d6fe52a96
[bytom/vapor.git] / application / mov / match / engine_test.go
1 package match
2
3 import (
4         "testing"
5
6         "github.com/bytom/vapor/application/mov/common"
7         "github.com/bytom/vapor/application/mov/mock"
8         "github.com/bytom/vapor/protocol/bc"
9         "github.com/bytom/vapor/protocol/bc/types"
10         "github.com/bytom/vapor/protocol/validation"
11 )
12
13 func TestGenerateMatchedTxs(t *testing.T) {
14         btc2eth := &common.TradePair{FromAssetID: &mock.BTC, ToAssetID: &mock.ETH}
15         eth2btc := &common.TradePair{FromAssetID: &mock.ETH, ToAssetID: &mock.BTC}
16         eth2eos := &common.TradePair{FromAssetID: &mock.ETH, ToAssetID: &mock.EOS}
17         eos2btc := &common.TradePair{FromAssetID: &mock.EOS, ToAssetID: &mock.BTC}
18
19         cases := []struct {
20                 desc            string
21                 tradePairs      []*common.TradePair
22                 initStoreOrders []*common.Order
23                 wantMatchedTxs  []*types.Tx
24         }{
25                 {
26                         desc:       "full matched",
27                         tradePairs: []*common.TradePair{btc2eth, eth2btc},
28                         initStoreOrders: []*common.Order{
29                                 mock.Btc2EthOrders[0], mock.Btc2EthOrders[1],
30                                 mock.Eth2BtcOrders[0],
31                         },
32                         wantMatchedTxs: []*types.Tx{
33                                 mock.MatchedTxs[1],
34                         },
35                 },
36                 {
37                         desc:       "partial matched",
38                         tradePairs: []*common.TradePair{btc2eth, eth2btc},
39                         initStoreOrders: []*common.Order{
40                                 mock.Btc2EthOrders[0], mock.Btc2EthOrders[1],
41                                 mock.Eth2BtcOrders[1],
42                         },
43                         wantMatchedTxs: []*types.Tx{
44                                 mock.MatchedTxs[0],
45                         },
46                 },
47                 {
48                         desc:       "partial matched and continue to match",
49                         tradePairs: []*common.TradePair{btc2eth, eth2btc},
50                         initStoreOrders: []*common.Order{
51                                 mock.Btc2EthOrders[0], mock.Btc2EthOrders[1],
52                                 mock.Eth2BtcOrders[2],
53                         },
54                         wantMatchedTxs: []*types.Tx{
55                                 mock.MatchedTxs[2],
56                                 mock.MatchedTxs[3],
57                         },
58                 },
59                 {
60                         desc:       "unable to match",
61                         tradePairs: []*common.TradePair{btc2eth, eth2btc},
62                         initStoreOrders: []*common.Order{
63                                 mock.Btc2EthOrders[1],
64                                 mock.Eth2BtcOrders[0],
65                         },
66                         wantMatchedTxs: []*types.Tx{},
67                 },
68                 {
69                         desc:       "cycle match",
70                         tradePairs: []*common.TradePair{btc2eth, eth2eos, eos2btc},
71                         initStoreOrders: []*common.Order{
72                                 mock.Btc2EthOrders[0], mock.Eth2EosOrders[0], mock.Eos2BtcOrders[0],
73                         },
74                         wantMatchedTxs: []*types.Tx{
75                                 mock.MatchedTxs[6],
76                         },
77                 },
78                 {
79                         desc:       "multiple assets as a fee",
80                         tradePairs: []*common.TradePair{btc2eth, eth2btc},
81                         initStoreOrders: []*common.Order{
82                                 mock.Btc2EthOrders[0], mock.Eth2BtcOrders[3],
83                         },
84                         wantMatchedTxs: []*types.Tx{
85                                 mock.MatchedTxs[11],
86                         },
87                 },
88         }
89
90         for i, c := range cases {
91                 movStore := mock.NewMovStore([]*common.TradePair{btc2eth, eth2btc}, c.initStoreOrders)
92                 matchEngine := NewEngine(NewOrderBook(movStore, nil, nil), NewDefaultFeeStrategy(), mock.RewardProgram)
93                 var gotMatchedTxs []*types.Tx
94                 for matchEngine.HasMatchedTx(c.tradePairs...) {
95                         matchedTx, err := matchEngine.NextMatchedTx(c.tradePairs...)
96                         if err != nil {
97                                 t.Fatal(err)
98                         }
99
100                         gotMatchedTxs = append(gotMatchedTxs, matchedTx)
101                 }
102
103                 if len(c.wantMatchedTxs) != len(gotMatchedTxs) {
104                         t.Errorf("#%d(%s) the length of got matched tx is not equals want matched tx", i, c.desc)
105                         continue
106                 }
107
108                 for j, gotMatchedTx := range gotMatchedTxs {
109                         if _, err := validation.ValidateTx(gotMatchedTx.Tx, &bc.Block{BlockHeader: &bc.BlockHeader{Version: 1}}); err != nil {
110                                 t.Fatal(err)
111                         }
112
113                         c.wantMatchedTxs[j].Version = 1
114                         byteData, err := c.wantMatchedTxs[j].MarshalText()
115                         if err != nil {
116                                 t.Fatal(err)
117                         }
118
119                         c.wantMatchedTxs[j].SerializedSize = uint64(len(byteData))
120                         wantMatchedTx := types.NewTx(c.wantMatchedTxs[j].TxData)
121                         if gotMatchedTx.ID != wantMatchedTx.ID {
122                                 t.Errorf("#%d(%s) the tx hash of got matched tx: %s is not equals want matched tx: %s", i, c.desc, gotMatchedTx.ID.String(), wantMatchedTx.ID.String())
123                         }
124                 }
125         }
126 }
127
128 func TestValidateTradePairs(t *testing.T) {
129         cases := []struct {
130                 desc       string
131                 tradePairs []*common.TradePair
132                 wantError  bool
133         }{
134                 {
135                         desc: "valid case of two trade pairs",
136                         tradePairs: []*common.TradePair{
137                                 {
138                                         FromAssetID: &mock.BTC,
139                                         ToAssetID:   &mock.ETH,
140                                 },
141                                 {
142                                         FromAssetID: &mock.ETH,
143                                         ToAssetID:   &mock.BTC,
144                                 },
145                         },
146                         wantError: false,
147                 },
148                 {
149                         desc: "invalid case of two trade pairs",
150                         tradePairs: []*common.TradePair{
151                                 {
152                                         FromAssetID: &mock.BTC,
153                                         ToAssetID:   &mock.ETH,
154                                 },
155                                 {
156                                         FromAssetID: &mock.ETH,
157                                         ToAssetID:   &mock.EOS,
158                                 },
159                         },
160                         wantError: true,
161                 },
162                 {
163                         desc: "valid case of three trade pairs",
164                         tradePairs: []*common.TradePair{
165                                 {
166                                         FromAssetID: &mock.BTC,
167                                         ToAssetID:   &mock.ETH,
168                                 },
169                                 {
170                                         FromAssetID: &mock.ETH,
171                                         ToAssetID:   &mock.EOS,
172                                 },
173                                 {
174                                         FromAssetID: &mock.EOS,
175                                         ToAssetID:   &mock.BTC,
176                                 },
177                         },
178                         wantError: false,
179                 },
180                 {
181                         desc: "invalid case of three trade pairs",
182                         tradePairs: []*common.TradePair{
183                                 {
184                                         FromAssetID: &mock.BTC,
185                                         ToAssetID:   &mock.ETH,
186                                 },
187                                 {
188                                         FromAssetID: &mock.ETH,
189                                         ToAssetID:   &mock.BTC,
190                                 },
191                                 {
192                                         FromAssetID: &mock.BTC,
193                                         ToAssetID:   &mock.BTC,
194                                 },
195                         },
196                         wantError: true,
197                 },
198                 {
199                         desc: "valid case 2 of three trade pairs",
200                         tradePairs: []*common.TradePair{
201                                 {
202                                         FromAssetID: &mock.BTC,
203                                         ToAssetID:   &mock.ETH,
204                                 },
205                                 {
206                                         FromAssetID: &mock.EOS,
207                                         ToAssetID:   &mock.BTC,
208                                 },
209                                 {
210                                         FromAssetID: &mock.ETH,
211                                         ToAssetID:   &mock.EOS,
212                                 },
213                         },
214                         wantError: false,
215                 },
216         }
217
218         for i, c := range cases {
219                 err := validateTradePairs(c.tradePairs)
220                 if c.wantError && err == nil {
221                         t.Errorf("#%d(%s): want error, got no error", i, c.desc)
222                 }
223
224                 if !c.wantError && err != nil {
225                         t.Errorf("#%d(%s): want no error, got error (%v)", i, c.desc, err)
226                 }
227         }
228 }
229
230 func TestIsMatched(t *testing.T) {
231         cases := []struct {
232                 desc        string
233                 orders      []*common.Order
234                 wantMatched bool
235         }{
236                 {
237                         desc: "ratio is equals",
238                         orders: []*common.Order{
239                                 {
240                                         FromAssetID:      &mock.BTC,
241                                         ToAssetID:        &mock.ETH,
242                                         RatioNumerator:   6250,
243                                         RatioDenominator: 3,
244                                 },
245                                 {
246                                         FromAssetID:      &mock.ETH,
247                                         ToAssetID:        &mock.BTC,
248                                         RatioNumerator:   3,
249                                         RatioDenominator: 6250,
250                                 },
251                         },
252                         wantMatched: true,
253                 },
254                 {
255                         desc: "ratio is equals, and numerator and denominator are multiples of the opposite",
256                         orders: []*common.Order{
257                                 {
258                                         FromAssetID:      &mock.BTC,
259                                         ToAssetID:        &mock.ETH,
260                                         RatioNumerator:   6250,
261                                         RatioDenominator: 3,
262                                 },
263                                 {
264                                         FromAssetID:      &mock.ETH,
265                                         ToAssetID:        &mock.BTC,
266                                         RatioNumerator:   9,
267                                         RatioDenominator: 18750,
268                                 },
269                         },
270                         wantMatched: true,
271                 },
272                 {
273                         desc: "matched with a slight diff",
274                         orders: []*common.Order{
275                                 {
276                                         FromAssetID:      &mock.BTC,
277                                         ToAssetID:        &mock.ETH,
278                                         RatioNumerator:   62500000000000000,
279                                         RatioDenominator: 30000000000001,
280                                 },
281                                 {
282                                         FromAssetID:      &mock.ETH,
283                                         ToAssetID:        &mock.BTC,
284                                         RatioNumerator:   3,
285                                         RatioDenominator: 6250,
286                                 },
287                         },
288                         wantMatched: true,
289                 },
290                 {
291                         desc: "not matched with a slight diff",
292                         orders: []*common.Order{
293                                 {
294                                         FromAssetID:      &mock.BTC,
295                                         ToAssetID:        &mock.ETH,
296                                         RatioNumerator:   62500000000000001,
297                                         RatioDenominator: 30000000000000,
298                                 },
299                                 {
300                                         FromAssetID:      &mock.ETH,
301                                         ToAssetID:        &mock.BTC,
302                                         RatioNumerator:   3,
303                                         RatioDenominator: 6250,
304                                 },
305                         },
306                         wantMatched: false,
307                 },
308                 {
309                         desc: "ring matched",
310                         orders: []*common.Order{
311                                 {
312                                         FromAssetID:      &mock.BTC,
313                                         ToAssetID:        &mock.ETH,
314                                         RatioNumerator:   2000000003,
315                                         RatioDenominator: 100000001,
316                                 },
317                                 {
318                                         FromAssetID:      &mock.ETH,
319                                         ToAssetID:        &mock.EOS,
320                                         RatioNumerator:   400000000001,
321                                         RatioDenominator: 2000000003,
322                                 },
323                                 {
324                                         FromAssetID:      &mock.EOS,
325                                         ToAssetID:        &mock.BTC,
326                                         RatioNumerator:   100000001,
327                                         RatioDenominator: 400000000001,
328                                 },
329                         },
330                         wantMatched: true,
331                 },
332                 {
333                         desc: "ring matched with a slight diff",
334                         orders: []*common.Order{
335                                 {
336                                         FromAssetID:      &mock.BTC,
337                                         ToAssetID:        &mock.ETH,
338                                         RatioNumerator:   2000000003,
339                                         RatioDenominator: 100000001,
340                                 },
341                                 {
342                                         FromAssetID:      &mock.ETH,
343                                         ToAssetID:        &mock.EOS,
344                                         RatioNumerator:   400000000001,
345                                         RatioDenominator: 2000000003,
346                                 },
347                                 {
348                                         FromAssetID:      &mock.EOS,
349                                         ToAssetID:        &mock.BTC,
350                                         RatioNumerator:   100000000,
351                                         RatioDenominator: 400000000001,
352                                 },
353                         },
354                         wantMatched: true,
355                 },
356                 {
357                         desc: "ring fail matched with a slight diff",
358                         orders: []*common.Order{
359                                 {
360                                         FromAssetID:      &mock.BTC,
361                                         ToAssetID:        &mock.ETH,
362                                         RatioNumerator:   2000000003,
363                                         RatioDenominator: 100000001,
364                                 },
365                                 {
366                                         FromAssetID:      &mock.ETH,
367                                         ToAssetID:        &mock.EOS,
368                                         RatioNumerator:   400000000001,
369                                         RatioDenominator: 2000000003,
370                                 },
371                                 {
372                                         FromAssetID:      &mock.EOS,
373                                         ToAssetID:        &mock.BTC,
374                                         RatioNumerator:   100000002,
375                                         RatioDenominator: 400000000001,
376                                 },
377                         },
378                         wantMatched: false,
379                 },
380         }
381
382         for i, c := range cases {
383                 gotMatched := IsMatched(c.orders)
384                 if gotMatched != c.wantMatched {
385                         t.Errorf("#%d(%s) got matched:%v, want matched:%v", i, c.desc, gotMatched, c.wantMatched)
386                 }
387         }
388 }