OSDN Git Service

022051f58741cee76c3881afd3d0954d72be7dfa
[bytom/vapor.git] / application / mov / database / mov_store_test.go
1 package database
2
3 import (
4         "encoding/json"
5         "errors"
6         "io/ioutil"
7         "os"
8         "testing"
9
10         "github.com/stretchr/testify/require"
11
12         "github.com/bytom/vapor/application/mov/common"
13         "github.com/bytom/vapor/database/leveldb"
14         dbm "github.com/bytom/vapor/database/leveldb"
15         "github.com/bytom/vapor/protocol/bc"
16         "github.com/bytom/vapor/protocol/bc/types"
17         "github.com/bytom/vapor/testutil"
18 )
19
20 var (
21         assetID1 = &bc.AssetID{V0: 1}
22         assetID2 = &bc.AssetID{V0: 2}
23         assetID3 = &bc.AssetID{V0: 3}
24         assetID4 = &bc.AssetID{V0: 4}
25         assetID5 = &bc.AssetID{V0: 5}
26         assetID6 = &bc.AssetID{V0: 6}
27         assetID7 = &bc.AssetID{V0: 7}
28         assetID8 = &bc.AssetID{V0: 8}
29         
30         orderProgram = testutil.MustDecodeHexString("0020184e1cc4ee4845023888810a79eed7a42c02c544cf2c61ceac05e176d575bd4603ed4e0e0210272200204775b9e167e2c1ffe57ae3e5088af69e518be010529b5fdadf4be97656084eec20a3e21b55f44403884457166ad5847fdb5489512ba9611eee466efb9f94319143")
31         sellerProgram = testutil.MustDecodeHexString("00204775b9e167e2c1ffe57ae3e5088af69e518be010529b5fdadf4be97656084eec")
32
33         mockOrders = []*common.Order{
34                 &common.Order{
35                         FromAssetID:      assetID1,
36                         ToAssetID:        assetID2,
37                         RatioNumerator:   100090,
38                         RatioDenominator: 100000,
39                         Utxo: &common.MovUtxo{
40                                 SourceID:       &bc.Hash{V0: 21},
41                                 Amount:         1,
42                                 SourcePos:      0,
43                                 ControlProgram: orderProgram,
44                         },
45                         SellerProgram: sellerProgram,
46                 },
47                 &common.Order{
48                         FromAssetID:      assetID1,
49                         ToAssetID:        assetID2,
50                         RatioNumerator:   90,
51                         RatioDenominator: 100000,
52                         Utxo: &common.MovUtxo{
53                                 SourceID:       &bc.Hash{V0: 22},
54                                 Amount:         1,
55                                 SourcePos:      0,
56                                 ControlProgram: orderProgram,
57                         },
58                         SellerProgram: sellerProgram,
59                 },
60                 &common.Order{
61                         FromAssetID:      assetID1,
62                         ToAssetID:        assetID2,
63                         RatioNumerator:   97,
64                         RatioDenominator: 100000,
65                         Utxo: &common.MovUtxo{
66                                 SourceID:       &bc.Hash{V0: 23},
67                                 Amount:         1,
68                                 SourcePos:      0,
69                                 ControlProgram: orderProgram,
70                         },
71                         SellerProgram: sellerProgram,
72                 },
73                 &common.Order{
74                         FromAssetID:      assetID1,
75                         ToAssetID:        assetID2,
76                         RatioNumerator:   98,
77                         RatioDenominator: 100000,
78                         Utxo: &common.MovUtxo{
79                                 SourceID:       &bc.Hash{V0: 13},
80                                 Amount:         1,
81                                 SourcePos:      0,
82                                 ControlProgram: orderProgram,
83                         },
84                         SellerProgram: sellerProgram,
85                 },
86                 &common.Order{
87                         FromAssetID:      assetID1,
88                         ToAssetID:        assetID2,
89                         RatioNumerator:   98,
90                         RatioDenominator: 100000,
91                         Utxo: &common.MovUtxo{
92                                 SourceID:       &bc.Hash{V0: 24},
93                                 Amount:         10,
94                                 SourcePos:      1,
95                                 ControlProgram: orderProgram,
96                         },
97                         SellerProgram: sellerProgram,
98                 },
99                 &common.Order{
100                         FromAssetID:      assetID1,
101                         ToAssetID:        assetID2,
102                         RatioNumerator:   99,
103                         RatioDenominator: 100000,
104                         Utxo: &common.MovUtxo{
105                                 SourceID:       &bc.Hash{V0: 24},
106                                 Amount:         1,
107                                 SourcePos:      0,
108                                 ControlProgram: orderProgram,
109                         },
110                         SellerProgram: sellerProgram,
111                 },
112                 &common.Order{
113                         FromAssetID:      assetID1,
114                         ToAssetID:        assetID2,
115                         RatioNumerator:   96,
116                         RatioDenominator: 100000,
117                         Utxo: &common.MovUtxo{
118                                 SourceID:       &bc.Hash{V0: 25},
119                                 Amount:         1,
120                                 SourcePos:      0,
121                                 ControlProgram: orderProgram,
122                         },
123                         SellerProgram: sellerProgram,
124                 },
125                 &common.Order{
126                         FromAssetID:      assetID1,
127                         ToAssetID:        assetID2,
128                         RatioNumerator:   95,
129                         RatioDenominator: 100000,
130                         Utxo: &common.MovUtxo{
131                                 SourceID:       &bc.Hash{V0: 26},
132                                 Amount:         1,
133                                 SourcePos:      0,
134                                 ControlProgram: orderProgram,
135                         },
136                         SellerProgram: sellerProgram,
137                 },
138                 &common.Order{
139                         FromAssetID:      assetID1,
140                         ToAssetID:        assetID2,
141                         RatioNumerator:   90,
142                         RatioDenominator: 100000,
143                         Utxo: &common.MovUtxo{
144                                 SourceID:       &bc.Hash{V0: 1},
145                                 Amount:         1,
146                                 SourcePos:      0,
147                                 ControlProgram: orderProgram,
148                         },
149                         SellerProgram: sellerProgram,
150                 },
151                 &common.Order{
152                         FromAssetID:      assetID1,
153                         ToAssetID:        assetID2,
154                         RatioNumerator:   90,
155                         RatioDenominator: 100000,
156                         Utxo: &common.MovUtxo{
157                                 SourceID:       &bc.Hash{V0: 2},
158                                 Amount:         1,
159                                 SourcePos:      0,
160                                 ControlProgram: orderProgram,
161                         },
162                         SellerProgram: sellerProgram,
163                 },
164                 &common.Order{
165                         FromAssetID:      assetID3,
166                         ToAssetID:        assetID2,
167                         RatioNumerator:   96,
168                         RatioDenominator: 100000,
169                         Utxo: &common.MovUtxo{
170                                 SourceID:       &bc.Hash{V0: 33},
171                                 Amount:         1,
172                                 SourcePos:      0,
173                                 ControlProgram: orderProgram,
174                         },
175                         SellerProgram: sellerProgram,
176                 },
177                 &common.Order{
178                         FromAssetID:      assetID4,
179                         ToAssetID:        assetID2,
180                         RatioNumerator:   95,
181                         RatioDenominator: 100000,
182                         Utxo: &common.MovUtxo{
183                                 SourceID:       &bc.Hash{V0: 34},
184                                 Amount:         1,
185                                 SourcePos:      0,
186                                 ControlProgram: orderProgram,
187                         },
188                         SellerProgram: sellerProgram,
189                 },
190                 &common.Order{
191                         FromAssetID:      assetID4,
192                         ToAssetID:        assetID2,
193                         RatioNumerator:   96,
194                         RatioDenominator: 100000,
195                         Utxo: &common.MovUtxo{
196                                 SourceID:       &bc.Hash{V0: 36},
197                                 Amount:         1,
198                                 SourcePos:      0,
199                                 ControlProgram: orderProgram,
200                         },
201                         SellerProgram: sellerProgram,
202                 },
203                 &common.Order{
204                         FromAssetID:      assetID5,
205                         ToAssetID:        assetID2,
206                         RatioNumerator:   96,
207                         RatioDenominator: 100000,
208                         Utxo: &common.MovUtxo{
209                                 SourceID:       &bc.Hash{V0: 37},
210                                 Amount:         1,
211                                 SourcePos:      0,
212                                 ControlProgram: orderProgram,
213                         },
214                         SellerProgram: sellerProgram,
215                 },
216                 &common.Order{
217                         FromAssetID:      assetID6,
218                         ToAssetID:        assetID2,
219                         RatioNumerator:   98,
220                         RatioDenominator: 100000,
221                         Utxo: &common.MovUtxo{
222                                 SourceID:       &bc.Hash{V0: 38},
223                                 Amount:         1,
224                                 SourcePos:      0,
225                                 ControlProgram: orderProgram,
226                         },
227                         SellerProgram: sellerProgram,
228                 },
229         }
230 )
231
232 func TestGetAssetIDFromTradePairKey(t *testing.T) {
233         b := calcTradePairKey(assetID1, assetID2)
234         gotA := getAssetIDFromTradePairKey(b, fromAssetIDPos)
235         gotB := getAssetIDFromTradePairKey(b, toAssetIDPos)
236
237         if *gotA != *assetID1 {
238                 t.Fatalf("got wrong from asset id got %s, want %s", gotA.String(), assetID1.String())
239         }
240
241         if *gotB != *assetID2 {
242                 t.Fatalf("got wrong to asset id got %s, want %s", gotB.String(), assetID2.String())
243         }
244 }
245
246 func TestSortOrderKey(t *testing.T) {
247         dirname, err := ioutil.TempDir("", "db_common_test")
248         require.Nil(t, err)
249
250         db, err := leveldb.NewGoLevelDB("testdb", dirname)
251         if err != nil {
252                 t.Fatal(err)
253         }
254
255         defer func() {
256                 db.Close()
257                 os.RemoveAll(dirname)
258         }()
259
260         type expectedData struct {
261                 rate     float64
262                 utxoHash string
263         }
264
265         cases := []struct {
266                 orders []*common.Order
267                 want   []expectedData
268         }{
269                 {
270                         orders: []*common.Order{
271                                 &common.Order{
272                                         FromAssetID:      &bc.AssetID{V0: 1},
273                                         ToAssetID:        &bc.AssetID{V0: 0},
274                                         RatioNumerator:   100090,
275                                         RatioDenominator: 100000,
276                                         Utxo: &common.MovUtxo{
277                                                 SourceID:       &bc.Hash{V0: 21},
278                                                 Amount:         1,
279                                                 SourcePos:      0,
280                                                 ControlProgram: []byte("aa"),
281                                         },
282                                 },
283                                 &common.Order{
284                                         FromAssetID:      &bc.AssetID{V0: 1},
285                                         ToAssetID:        &bc.AssetID{V0: 0},
286                                         RatioNumerator:   90,
287                                         RatioDenominator: 100000,
288                                         Utxo: &common.MovUtxo{
289                                                 SourceID:       &bc.Hash{V0: 22},
290                                                 Amount:         1,
291                                                 SourcePos:      0,
292                                                 ControlProgram: []byte("aa"),
293                                         },
294                                 },
295                                 &common.Order{
296                                         FromAssetID:      &bc.AssetID{V0: 1},
297                                         ToAssetID:        &bc.AssetID{V0: 0},
298                                         RatioNumerator:   97,
299                                         RatioDenominator: 100000,
300                                         Utxo: &common.MovUtxo{
301                                                 SourceID:       &bc.Hash{V0: 23},
302                                                 Amount:         1,
303                                                 SourcePos:      0,
304                                                 ControlProgram: []byte("aa"),
305                                         },
306                                 },
307                                 &common.Order{
308                                         FromAssetID:      &bc.AssetID{V0: 1},
309                                         ToAssetID:        &bc.AssetID{V0: 0},
310                                         RatioNumerator:   98,
311                                         RatioDenominator: 100000,
312                                         Utxo: &common.MovUtxo{
313                                                 SourceID:       &bc.Hash{V0: 13},
314                                                 Amount:         1,
315                                                 SourcePos:      0,
316                                                 ControlProgram: []byte("aa"),
317                                         },
318                                 },
319                                 &common.Order{
320                                         FromAssetID:      &bc.AssetID{V0: 1},
321                                         ToAssetID:        &bc.AssetID{V0: 0},
322                                         RatioNumerator:   98,
323                                         RatioDenominator: 100000,
324                                         Utxo: &common.MovUtxo{
325                                                 SourceID:       &bc.Hash{V0: 24},
326                                                 Amount:         10,
327                                                 SourcePos:      1,
328                                                 ControlProgram: []byte("aa"),
329                                         },
330                                 },
331                                 &common.Order{
332                                         FromAssetID:      &bc.AssetID{V0: 1},
333                                         ToAssetID:        &bc.AssetID{V0: 0},
334                                         RatioNumerator:   98,
335                                         RatioDenominator: 100000,
336                                         Utxo: &common.MovUtxo{
337                                                 SourceID:       &bc.Hash{V0: 25},
338                                                 Amount:         10,
339                                                 SourcePos:      1,
340                                                 ControlProgram: []byte("aa"),
341                                         },
342                                 },
343                                 &common.Order{
344                                         FromAssetID:      &bc.AssetID{V0: 1},
345                                         ToAssetID:        &bc.AssetID{V0: 0},
346                                         RatioNumerator:   98,
347                                         RatioDenominator: 100000,
348                                         Utxo: &common.MovUtxo{
349                                                 SourceID:       &bc.Hash{V0: 26},
350                                                 Amount:         10,
351                                                 SourcePos:      1,
352                                                 ControlProgram: []byte("aa"),
353                                         },
354                                 },
355                                 &common.Order{
356                                         FromAssetID:      &bc.AssetID{V0: 1},
357                                         ToAssetID:        &bc.AssetID{V0: 0},
358                                         RatioNumerator:   98,
359                                         RatioDenominator: 100000,
360                                         Utxo: &common.MovUtxo{
361                                                 SourceID:       &bc.Hash{V0: 27},
362                                                 Amount:         10,
363                                                 SourcePos:      1,
364                                                 ControlProgram: []byte("aa"),
365                                         },
366                                 },
367                                 &common.Order{
368                                         FromAssetID:      &bc.AssetID{V0: 1},
369                                         ToAssetID:        &bc.AssetID{V0: 0},
370                                         RatioNumerator:   99,
371                                         RatioDenominator: 100000,
372                                         Utxo: &common.MovUtxo{
373                                                 SourceID:       &bc.Hash{V0: 24},
374                                                 Amount:         1,
375                                                 SourcePos:      0,
376                                                 ControlProgram: []byte("aa"),
377                                         },
378                                 },
379                                 &common.Order{
380                                         FromAssetID:      &bc.AssetID{V0: 1},
381                                         ToAssetID:        &bc.AssetID{V0: 0},
382                                         RatioNumerator:   96,
383                                         RatioDenominator: 100000,
384                                         Utxo: &common.MovUtxo{
385                                                 SourceID:       &bc.Hash{V0: 25},
386                                                 Amount:         1,
387                                                 SourcePos:      0,
388                                                 ControlProgram: []byte("aa"),
389                                         },
390                                 },
391                                 &common.Order{
392                                         FromAssetID:      &bc.AssetID{V0: 1},
393                                         ToAssetID:        &bc.AssetID{V0: 0},
394                                         RatioNumerator:   95,
395                                         RatioDenominator: 100000,
396                                         Utxo: &common.MovUtxo{
397                                                 SourceID:       &bc.Hash{V0: 26},
398                                                 Amount:         1,
399                                                 SourcePos:      0,
400                                                 ControlProgram: []byte("aa"),
401                                         },
402                                 },
403                                 &common.Order{
404                                         FromAssetID:      &bc.AssetID{V0: 1},
405                                         ToAssetID:        &bc.AssetID{V0: 0},
406                                         RatioNumerator:   91,
407                                         RatioDenominator: 100000,
408                                         Utxo: &common.MovUtxo{
409                                                 SourceID:       &bc.Hash{V0: 26},
410                                                 Amount:         1,
411                                                 SourcePos:      0,
412                                                 ControlProgram: []byte("aa"),
413                                         },
414                                 },
415                                 &common.Order{
416                                         FromAssetID:      &bc.AssetID{V0: 1},
417                                         ToAssetID:        &bc.AssetID{V0: 0},
418                                         RatioNumerator:   92,
419                                         RatioDenominator: 100000,
420                                         Utxo: &common.MovUtxo{
421                                                 SourceID:       &bc.Hash{V0: 27},
422                                                 Amount:         1,
423                                                 SourcePos:      0,
424                                                 ControlProgram: []byte("aa"),
425                                         },
426                                 },
427                                 &common.Order{
428                                         FromAssetID:      &bc.AssetID{V0: 1},
429                                         ToAssetID:        &bc.AssetID{V0: 0},
430                                         RatioNumerator:   93,
431                                         RatioDenominator: 100000,
432                                         Utxo: &common.MovUtxo{
433                                                 SourceID:       &bc.Hash{V0: 28},
434                                                 Amount:         1,
435                                                 SourcePos:      0,
436                                                 ControlProgram: []byte("aa"),
437                                         },
438                                 },
439                                 &common.Order{
440                                         FromAssetID:      &bc.AssetID{V0: 1},
441                                         ToAssetID:        &bc.AssetID{V0: 0},
442                                         RatioNumerator:   94,
443                                         RatioDenominator: 100000,
444                                         Utxo: &common.MovUtxo{
445                                                 SourceID:       &bc.Hash{V0: 29},
446                                                 Amount:         1,
447                                                 SourcePos:      0,
448                                                 ControlProgram: []byte("aa"),
449                                         },
450                                 },
451                                 &common.Order{
452                                         FromAssetID:      &bc.AssetID{V0: 1},
453                                         ToAssetID:        &bc.AssetID{V0: 0},
454                                         RatioNumerator:   77,
455                                         RatioDenominator: 100000,
456                                         Utxo: &common.MovUtxo{
457                                                 SourceID:       &bc.Hash{V0: 30},
458                                                 Amount:         1,
459                                                 SourcePos:      0,
460                                                 ControlProgram: []byte("aa"),
461                                         },
462                                 },
463                                 &common.Order{
464                                         FromAssetID:      &bc.AssetID{V0: 1},
465                                         ToAssetID:        &bc.AssetID{V0: 0},
466                                         RatioNumerator:   88,
467                                         RatioDenominator: 100000,
468                                         Utxo: &common.MovUtxo{
469                                                 SourceID:       &bc.Hash{V0: 31},
470                                                 Amount:         1,
471                                                 SourcePos:      0,
472                                                 ControlProgram: []byte("aa"),
473                                         },
474                                 },
475                                 &common.Order{
476                                         FromAssetID:      &bc.AssetID{V0: 1},
477                                         ToAssetID:        &bc.AssetID{V0: 0},
478                                         RatioNumerator:   9999999521,
479                                         RatioDenominator: 10000,
480                                         Utxo: &common.MovUtxo{
481                                                 SourceID:       &bc.Hash{V0: 32},
482                                                 Amount:         1,
483                                                 SourcePos:      0,
484                                                 ControlProgram: []byte("aa"),
485                                         },
486                                 },
487                                 &common.Order{
488                                         FromAssetID:      &bc.AssetID{V0: 1},
489                                         ToAssetID:        &bc.AssetID{V0: 0},
490                                         RatioNumerator:   8888887954,
491                                         RatioDenominator: 10000,
492                                         Utxo: &common.MovUtxo{
493                                                 SourceID:       &bc.Hash{V0: 33},
494                                                 Amount:         1,
495                                                 SourcePos:      0,
496                                                 ControlProgram: []byte("aa"),
497                                         },
498                                 },
499                         },
500                         want: []expectedData{
501                                 expectedData{
502                                         rate:     0.00077,
503                                         utxoHash: "f1b85307cf1f4eb6b193b6fc289413fdbb12bc362ced399762589b016e54dd02",
504                                 },
505                                 expectedData{
506                                         rate:     0.00088,
507                                         utxoHash: "49ef60af0f24962ed129a73142048ed0cb589041c629353932e3c3e0a4e822ba",
508                                 },
509                                 expectedData{
510                                         rate:     0.00090,
511                                         utxoHash: "67b2ac6ea71b271e72836e162811866f291ed2fab106c43519ca0c94ef8a5dce",
512                                 },
513                                 expectedData{
514                                         rate:     0.00091,
515                                         utxoHash: "47ff45b7b530512142981c2cee82faad63d6c9e7ffed0e72c3e42668f13b296f",
516                                 },
517                                 expectedData{
518                                         rate:     0.00092,
519                                         utxoHash: "b750d0b95f38043362c8335f242f97cfd3e1cada8fd171b914471a16cc0f14c6",
520                                 },
521                                 expectedData{
522                                         rate:     0.00093,
523                                         utxoHash: "04386ef57f0ca1be0a9be46c413900adbc0ab1e90e773959924aa73ca62edf64",
524                                 },
525                                 expectedData{
526                                         rate:     0.00094,
527                                         utxoHash: "c0fe6227c50da350a5e7b4ff85c18e9c901c323521067b9142acd128cf13ae82",
528                                 },
529                                 expectedData{
530                                         rate:     0.00095,
531                                         utxoHash: "47ff45b7b530512142981c2cee82faad63d6c9e7ffed0e72c3e42668f13b296f",
532                                 },
533                                 expectedData{
534                                         rate:     0.00096,
535                                         utxoHash: "bc92df1cbd20c98b0d18c9d93422a770849235867522a08e492196d16ed0a422",
536                                 },
537                                 expectedData{
538                                         rate:     0.00097,
539                                         utxoHash: "0cc0ded6fb337a3c5e6e4d008d6167dc58bdede43713898e914d65cda3b8499a",
540                                 },
541                                 expectedData{
542                                         rate:     0.00098,
543                                         utxoHash: "14b51a6103f75d9cacdf0f9551467588c687ed3b029e25c646d276720569e227",
544                                 },
545                                 expectedData{
546                                         rate:     0.00098,
547                                         utxoHash: "1fa9fae83d0a5401a4e92f80636966486e763eecca588aa11dff02b415320602",
548                                 },
549                                 expectedData{
550                                         rate:     0.00098,
551                                         utxoHash: "6687d18ddbe4e7381a844e393ca3032a412285c9da6988eff182106e28ba09ca",
552                                 },
553                                 expectedData{
554                                         rate:     0.00098,
555                                         utxoHash: "841b1de7c871dfe6e2d1886809d9ae12ec45e570233b03879305232b096fda43",
556                                 },
557                                 expectedData{
558                                         rate:     0.00098,
559                                         utxoHash: "a4bc534c267d35a9eafc25cd66e0cb270a2537a51186605b7f7591bc567ab4c6",
560                                 },
561                                 expectedData{
562                                         rate:     0.00099,
563                                         utxoHash: "fdedf4117def659e07cc8a8ca318d21ae577a05e1a0197844b54d493bdae5854",
564                                 },
565                                 expectedData{
566                                         rate:     1.0009,
567                                         utxoHash: "20be3bd2d406bb7fe6627b32768fb2073e997b962a4badfa4384210fed2ab9c6",
568                                 },
569                                 expectedData{
570                                         rate:     888888.7954,
571                                         utxoHash: "72192f56b9525c74c6a9f0419563bc0da76b0f3d6e89d9decdb6e67786ac3909",
572                                 },
573                                 expectedData{
574                                         rate:     999999.9521,
575                                         utxoHash: "7886844334659b4feffc41528cf81192925d3aa4a5ccb3652200b9073b7d47c3",
576                                 },
577                         },
578                 },
579         }
580
581         for i, c := range cases {
582                 for _, order := range c.orders {
583                         key := calcOrderKey(order.FromAssetID, order.ToAssetID, order.UTXOHash(), order.Rate())
584                         data, err := json.Marshal(order.Utxo)
585                         if err != nil {
586                                 t.Fatal(err)
587                         }
588
589                         db.SetSync(key, data)
590                 }
591
592                 got := []expectedData{}
593                 itr := db.IteratorPrefixWithStart(nil, nil, false)
594                 for itr.Next() {
595                         key := itr.Key()
596                         pos := len(ordersPrefix) + assetIDLen*2
597                         b := [32]byte{}
598                         copy(b[:], key[pos+8:])
599                         utxoHash := bc.NewHash(b)
600
601                         got = append(got, expectedData{
602                                 rate:     getRateFromOrderKey(key),
603                                 utxoHash: utxoHash.String(),
604                         })
605                 }
606                 itr.Release()
607
608                 if !testutil.DeepEqual(c.want, got) {
609                         t.Errorf("case %v: got recovery status, got: %v, want: %v.", i, got, c.want)
610                 }
611         }
612 }
613
614 func TestMovStore(t *testing.T) {
615         cases := []struct {
616                 desc             string
617                 beforeOrders     []*common.Order
618                 beforeTradePairs []*common.TradePair
619                 beforeDBStatus   *common.MovDatabaseState
620                 addOrders        []*common.Order
621                 delOrders        []*common.Order
622                 blockHeader      *types.BlockHeader
623                 wantOrders       []*common.Order
624                 wantTradePairs   []*common.TradePair
625                 wantDBState      *common.MovDatabaseState
626         }{
627                 {
628                         desc: "add order",
629                         addOrders: []*common.Order{
630                                 mockOrders[0],
631                                 mockOrders[1],
632                                 mockOrders[2],
633                                 mockOrders[3],
634                                 mockOrders[4],
635                                 mockOrders[5],
636                                 mockOrders[6],
637                                 mockOrders[7],
638                         },
639                         blockHeader: &types.BlockHeader{Height: 1, PreviousBlockHash: bc.Hash{V0: 524821139490765641, V1: 2484214155808702787, V2: 9108473449351508820, V3: 7972721253564512122}},
640                         wantOrders: []*common.Order{
641                                 mockOrders[1],
642                                 mockOrders[7],
643                                 mockOrders[6],
644                                 mockOrders[2],
645                                 mockOrders[4],
646                                 mockOrders[3],
647                                 mockOrders[5],
648                                 mockOrders[0],
649                         },
650                         wantTradePairs: []*common.TradePair{
651                                 &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 8},
652                         },
653                         wantDBState: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
654                 },
655                 {
656                         desc: "del some order",
657                         beforeOrders: []*common.Order{
658                                 mockOrders[0],
659                                 mockOrders[1],
660                                 mockOrders[2],
661                                 mockOrders[3],
662                                 mockOrders[4],
663                                 mockOrders[5],
664                                 mockOrders[6],
665                                 mockOrders[7],
666                         },
667                         beforeTradePairs: []*common.TradePair{
668                                 &common.TradePair{
669                                         FromAssetID: assetID1,
670                                         ToAssetID:   assetID2,
671                                         Count:       8,
672                                 },
673                         },
674                         beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
675                         delOrders: []*common.Order{
676                                 mockOrders[0],
677                                 mockOrders[1],
678                                 mockOrders[2],
679                         },
680                         blockHeader: &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
681                         wantOrders: []*common.Order{
682                                 mockOrders[7],
683                                 mockOrders[6],
684                                 mockOrders[4],
685                                 mockOrders[3],
686                                 mockOrders[5],
687                         },
688                         wantTradePairs: []*common.TradePair{
689                                 &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 5},
690                         },
691                         wantDBState: &common.MovDatabaseState{Height: 2, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
692                 },
693                 {
694                         desc: "del all order",
695                         beforeOrders: []*common.Order{
696                                 mockOrders[0],
697                                 mockOrders[1],
698                                 mockOrders[2],
699                                 mockOrders[3],
700                                 mockOrders[4],
701                                 mockOrders[5],
702                                 mockOrders[6],
703                                 mockOrders[7],
704                         },
705                         beforeTradePairs: []*common.TradePair{
706                                 &common.TradePair{
707                                         FromAssetID: assetID1,
708                                         ToAssetID:   assetID2,
709                                         Count:       8,
710                                 },
711                         },
712                         beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
713                         delOrders: []*common.Order{
714                                 mockOrders[0],
715                                 mockOrders[1],
716                                 mockOrders[2],
717                                 mockOrders[3],
718                                 mockOrders[4],
719                                 mockOrders[5],
720                                 mockOrders[6],
721                                 mockOrders[7],
722                         },
723                         blockHeader:    &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
724                         wantOrders:     []*common.Order{},
725                         wantTradePairs: []*common.TradePair{},
726                         wantDBState:    &common.MovDatabaseState{Height: 2, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
727                 },
728                 {
729                         desc: "Add and delete the same trade pair", // Add and delete different transaction pairs
730                         beforeOrders: []*common.Order{
731                                 mockOrders[0],
732                                 mockOrders[1],
733                                 mockOrders[2],
734                                 mockOrders[3],
735                                 mockOrders[4],
736                                 mockOrders[5],
737                                 mockOrders[6],
738                                 mockOrders[7],
739                         },
740                         beforeTradePairs: []*common.TradePair{
741                                 &common.TradePair{
742                                         FromAssetID: assetID1,
743                                         ToAssetID:   assetID2,
744                                         Count:       8,
745                                 },
746                         },
747                         beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
748                         addOrders: []*common.Order{
749                                 mockOrders[8],
750                                 mockOrders[9],
751                         },
752                         delOrders: []*common.Order{
753                                 mockOrders[0],
754                                 mockOrders[1],
755                                 mockOrders[2],
756                                 mockOrders[3],
757                                 mockOrders[4],
758                                 mockOrders[5],
759                                 mockOrders[6],
760                                 mockOrders[7],
761                         },
762                         blockHeader: &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
763                         wantOrders: []*common.Order{
764                                 mockOrders[9],
765                                 mockOrders[8],
766                         },
767                         wantTradePairs: []*common.TradePair{
768                                 &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 2},
769                         },
770                         wantDBState: &common.MovDatabaseState{Height: 2, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
771                 },
772                 {
773                         desc: "Add and delete different transaction pairs",
774                         beforeOrders: []*common.Order{
775                                 mockOrders[0],
776                                 mockOrders[1],
777                                 mockOrders[2],
778                                 mockOrders[3],
779                                 mockOrders[4],
780                                 mockOrders[5],
781                                 mockOrders[6],
782                                 mockOrders[7],
783                                 mockOrders[10],
784                                 mockOrders[11],
785                         },
786                         beforeTradePairs: []*common.TradePair{
787                                 &common.TradePair{
788                                         FromAssetID: assetID1,
789                                         ToAssetID:   assetID2,
790                                         Count:       8,
791                                 },
792                                 &common.TradePair{
793                                         FromAssetID: assetID3,
794                                         ToAssetID:   assetID2,
795                                         Count:       1,
796                                 },
797                                 &common.TradePair{
798                                         FromAssetID: assetID4,
799                                         ToAssetID:   assetID2,
800                                         Count:       1,
801                                 },
802                         },
803                         beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
804                         addOrders: []*common.Order{
805                                 mockOrders[12],
806                                 mockOrders[13],
807                                 mockOrders[14],
808                         },
809                         delOrders: []*common.Order{
810                                 mockOrders[0],
811                                 mockOrders[1],
812                                 mockOrders[2],
813                                 mockOrders[3],
814                                 mockOrders[4],
815                                 mockOrders[5],
816                                 mockOrders[6],
817                                 mockOrders[7],
818                                 mockOrders[10],
819                         },
820                         blockHeader: &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
821                         wantOrders: []*common.Order{
822                                 mockOrders[11],
823                                 mockOrders[12],
824                                 mockOrders[13],
825                                 mockOrders[14],
826                         },
827                         wantTradePairs: []*common.TradePair{
828                                 &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID2, Count: 2},
829                                 &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID2, Count: 1},
830                                 &common.TradePair{FromAssetID: assetID6, ToAssetID: assetID2, Count: 1},
831                         },
832                         wantDBState: &common.MovDatabaseState{Height: 2, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
833                 },
834         }
835
836         initBlockHeader := &types.BlockHeader{
837                 Height:  0,
838                 Version: 1,
839         }
840
841         height := initBlockHeader.Height
842         hash := initBlockHeader.Hash()
843
844         defer os.RemoveAll("temp")
845         for i, c := range cases {
846                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
847                 movStore := NewLevelDBMovStore(testDB)
848                 if err := movStore.InitDBState(height, &hash); err != nil {
849                         t.Fatalf("case %d: InitDBState error %v.", i, err)
850                 }
851
852                 batch := movStore.db.NewBatch()
853                 tradePairsCnt := make(map[string]*common.TradePair)
854                 movStore.addOrders(batch, c.beforeOrders, tradePairsCnt)
855                 if len(c.beforeOrders) > 0 {
856                         tradePairsCnt = make(map[string]*common.TradePair)
857                         for _, tradePair := range c.beforeTradePairs {
858                                 tradePairsCnt[tradePair.Key()] = tradePair
859                         }
860                         movStore.updateTradePairs(batch, tradePairsCnt)
861                         movStore.saveMovDatabaseState(batch, c.beforeDBStatus)
862                 }
863                 batch.Write()
864
865                 if err := movStore.ProcessOrders(c.addOrders, c.delOrders, c.blockHeader); err != nil {
866                         t.Fatalf("case %d: ProcessOrders error %v.", i, err)
867                 }
868
869                 var gotOrders []*common.Order
870
871                 tmp, err := movStore.ListOrders(&common.Order{FromAssetID: assetID1, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
872                 if err != nil {
873                         t.Fatalf("case %d: ListOrders(assetID1 and assetID2) error %v.", i, err)
874                 }
875
876                 gotOrders = append(gotOrders, tmp...)
877
878                 tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID3, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
879                 if err != nil {
880                         t.Fatalf("case %d: ListOrders(assetID3 and assetID2)  error %v.", i, err)
881                 }
882
883                 gotOrders = append(gotOrders, tmp...)
884
885                 tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID4, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
886                 if err != nil {
887                         t.Fatalf("case %d: ListOrders(assetID4 and assetID2)  error %v.", i, err)
888                 }
889
890                 gotOrders = append(gotOrders, tmp...)
891
892                 tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID5, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
893                 if err != nil {
894                         t.Fatalf("case %d: ListOrders(assetID5 and assetID2)  error %v.", i, err)
895                 }
896
897                 gotOrders = append(gotOrders, tmp...)
898
899                 tmp, err = movStore.ListOrders(&common.Order{FromAssetID: assetID6, ToAssetID: assetID2, RatioNumerator: 0, RatioDenominator: 1})
900                 if err != nil {
901                         t.Fatalf("case %d: ListOrders(assetID6 and assetID2)  error %v.", i, err)
902                 }
903
904                 gotOrders = append(gotOrders, tmp...)
905
906                 if !testutil.DeepEqual(gotOrders, c.wantOrders) {
907                         t.Fatalf("case %d: got orders , gotOrders: %v, wantOrders: %v.", i, gotOrders, c.wantOrders)
908                 }
909
910                 gotTradePairs, err := movStore.ListTradePairsWithStart(nil, nil)
911                 if err != nil {
912                         t.Fatalf("case %d: ListTradePairsWithStart error %v.", i, err)
913                 }
914
915                 if !testutil.DeepEqual(gotTradePairs, c.wantTradePairs) {
916                         t.Fatalf("case %d: got tradePairs, gotTradePairs: %v, wantTradePairs: %v.", i, gotTradePairs, c.wantTradePairs)
917                 }
918
919                 gotDBState, err := movStore.GetMovDatabaseState()
920                 if err != nil {
921                         t.Fatalf("case %d: GetMovDatabaseState error %v.", i, err)
922                 }
923
924                 if !testutil.DeepEqual(gotDBState, c.wantDBState) {
925                         t.Fatalf("case %d: got tradePairs, gotDBState: %v, wantDBStatus: %v.", i, gotDBState, c.wantDBState)
926                 }
927
928                 testDB.Close()
929                 os.RemoveAll("temp")
930         }
931 }
932
933 func TestListOrders(t *testing.T) {
934         cases := []struct {
935                 desc        string
936                 storeOrders []*common.Order
937                 query       *common.Order
938                 wantOrders  []*common.Order
939         }{
940                 {
941                         desc:       "empty",
942                         query:      &common.Order{FromAssetID: assetID1, ToAssetID: assetID2},
943                         wantOrders: []*common.Order{},
944                 },
945                 {
946                         desc: "query from first",
947                         storeOrders: []*common.Order{
948                                 mockOrders[0],
949                                 mockOrders[1],
950                                 mockOrders[2],
951                                 mockOrders[3],
952                                 mockOrders[4],
953                                 mockOrders[5],
954                                 mockOrders[6],
955                                 mockOrders[7],
956                                 mockOrders[10],
957                         },
958                         query: &common.Order{FromAssetID: assetID1, ToAssetID: assetID2},
959                         wantOrders: []*common.Order{
960                                 mockOrders[1],
961                                 mockOrders[7],
962                                 mockOrders[6],
963                                 mockOrders[2],
964                                 mockOrders[4],
965                                 mockOrders[3],
966                                 mockOrders[5],
967                                 mockOrders[0],
968                         },
969                 },
970                 {
971                         desc: "query from middle",
972                         storeOrders: []*common.Order{
973                                 mockOrders[0],
974                                 mockOrders[1],
975                                 mockOrders[2],
976                                 mockOrders[3],
977                                 mockOrders[4],
978                                 mockOrders[5],
979                                 mockOrders[6],
980                                 mockOrders[7],
981                         },
982                         query: mockOrders[3],
983                         wantOrders: []*common.Order{
984                                 mockOrders[5],
985                                 mockOrders[0],
986                         },
987                 },
988         }
989
990         initBlockHeader := &types.BlockHeader{
991                 Height:  0,
992                 Version: 1,
993         }
994
995         height := initBlockHeader.Height
996         hash := initBlockHeader.Hash()
997
998         defer os.RemoveAll("temp")
999         for i, c := range cases {
1000                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
1001                 movStore := NewLevelDBMovStore(testDB)
1002                 if err := movStore.InitDBState(height, &hash); err != nil {
1003                         t.Fatalf("case %d: InitDBState error %v.", i, err)
1004                 }
1005
1006                 batch := movStore.db.NewBatch()
1007                 tradePairsCnt := make(map[string]*common.TradePair)
1008                 movStore.addOrders(batch, c.storeOrders, tradePairsCnt)
1009                 movStore.updateTradePairs(batch, tradePairsCnt)
1010                 batch.Write()
1011
1012                 gotOrders, err := movStore.ListOrders(c.query)
1013                 if err != nil {
1014                         t.Fatalf("case %d: ListOrders error %v.", i, err)
1015                 }
1016
1017                 if !testutil.DeepEqual(gotOrders, c.wantOrders) {
1018                         t.Fatalf("case %d: got orders , gotOrders: %v, wantOrders: %v.", i, gotOrders, c.wantOrders)
1019                 }
1020
1021                 testDB.Close()
1022                 os.RemoveAll("temp")
1023         }
1024 }
1025
1026 func TestAddOrders(t *testing.T) {
1027         cases := []struct {
1028                 desc         string
1029                 beforeOrders []*common.Order
1030                 addOrders    []*common.Order
1031                 wantOrders   []*common.Order
1032         }{
1033                 {
1034                         desc: "empty",
1035                         addOrders: []*common.Order{
1036                                 mockOrders[0],
1037                                 mockOrders[1],
1038                                 mockOrders[2],
1039                                 mockOrders[3],
1040                                 mockOrders[4],
1041                                 mockOrders[5],
1042                                 mockOrders[6],
1043                                 mockOrders[7],
1044                         },
1045                         wantOrders: []*common.Order{
1046                                 mockOrders[1],
1047                                 mockOrders[7],
1048                                 mockOrders[6],
1049                                 mockOrders[2],
1050                                 mockOrders[4],
1051                                 mockOrders[3],
1052                                 mockOrders[5],
1053                                 mockOrders[0],
1054                         },
1055                 },
1056                 {
1057                         desc: "Stored data already exists",
1058                         beforeOrders: []*common.Order{
1059                                 mockOrders[0],
1060                                 mockOrders[1],
1061                                 mockOrders[2],
1062                                 mockOrders[3],
1063                         },
1064                         addOrders: []*common.Order{
1065                                 mockOrders[4],
1066                                 mockOrders[5],
1067                                 mockOrders[6],
1068                                 mockOrders[7],
1069                         },
1070                         wantOrders: []*common.Order{
1071                                 mockOrders[1],
1072                                 mockOrders[7],
1073                                 mockOrders[6],
1074                                 mockOrders[2],
1075                                 mockOrders[4],
1076                                 mockOrders[3],
1077                                 mockOrders[5],
1078                                 mockOrders[0],
1079                         },
1080                 },
1081         }
1082
1083         initBlockHeader := &types.BlockHeader{
1084                 Height:  0,
1085                 Version: 1,
1086         }
1087
1088         height := initBlockHeader.Height
1089         hash := initBlockHeader.Hash()
1090
1091         defer os.RemoveAll("temp")
1092         for i, c := range cases {
1093                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
1094                 movStore := NewLevelDBMovStore(testDB)
1095                 if err := movStore.InitDBState(height, &hash); err != nil {
1096                         t.Fatalf("case %d: InitDBState error %v.", i, err)
1097                 }
1098
1099                 batch := movStore.db.NewBatch()
1100                 tradePairsCnt := make(map[string]*common.TradePair)
1101                 movStore.addOrders(batch, c.beforeOrders, tradePairsCnt)
1102                 movStore.updateTradePairs(batch, tradePairsCnt)
1103                 batch.Write()
1104
1105                 tradePairsCnt = make(map[string]*common.TradePair)
1106                 movStore.addOrders(batch, c.addOrders, tradePairsCnt)
1107                 batch.Write()
1108
1109                 gotOrders, err := movStore.ListOrders(&common.Order{FromAssetID: assetID1, ToAssetID: assetID2})
1110                 if err != nil {
1111                         t.Fatalf("case %d: ListOrders error %v.", i, err)
1112                 }
1113
1114                 if !testutil.DeepEqual(gotOrders, c.wantOrders) {
1115                         t.Fatalf("case %d: got orders , gotOrders: %v, wantOrders: %v.", i, gotOrders, c.wantOrders)
1116                 }
1117
1118                 testDB.Close()
1119                 os.RemoveAll("temp")
1120         }
1121 }
1122
1123 func TestDelOrders(t *testing.T) {
1124         cases := []struct {
1125                 desc         string
1126                 beforeOrders []*common.Order
1127                 delOrders    []*common.Order
1128                 wantOrders   []*common.Order
1129                 err          error
1130         }{
1131                 {
1132                         desc: "empty",
1133                         delOrders: []*common.Order{
1134                                 mockOrders[0],
1135                                 mockOrders[1],
1136                         },
1137                         wantOrders: []*common.Order{},
1138                         err:        errors.New("don't find trade pair"),
1139                 },
1140                 {
1141                         desc: "Delete existing data",
1142                         beforeOrders: []*common.Order{
1143                                 mockOrders[1],
1144                                 mockOrders[7],
1145                                 mockOrders[6],
1146                                 mockOrders[2],
1147                                 mockOrders[3],
1148                                 mockOrders[4],
1149                                 mockOrders[5],
1150                                 mockOrders[0],
1151                         },
1152                         delOrders: []*common.Order{
1153                                 mockOrders[4],
1154                                 mockOrders[5],
1155                                 mockOrders[6],
1156                                 mockOrders[7],
1157                         },
1158                         wantOrders: []*common.Order{
1159                                 mockOrders[1],
1160                                 mockOrders[2],
1161                                 mockOrders[3],
1162                                 mockOrders[0],
1163                         },
1164                         err: nil,
1165                 },
1166                 {
1167                         desc: "Delete all data",
1168                         beforeOrders: []*common.Order{
1169                                 mockOrders[7],
1170                                 mockOrders[6],
1171                                 mockOrders[5],
1172                         },
1173                         delOrders: []*common.Order{
1174                                 mockOrders[5],
1175                                 mockOrders[6],
1176                                 mockOrders[7],
1177                         },
1178                         wantOrders: []*common.Order{},
1179                         err:        nil,
1180                 },
1181         }
1182
1183         initBlockHeader := &types.BlockHeader{
1184                 Height:  0,
1185                 Version: 1,
1186         }
1187
1188         height := initBlockHeader.Height
1189         hash := initBlockHeader.Hash()
1190
1191         defer os.RemoveAll("temp")
1192         for i, c := range cases {
1193                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
1194                 movStore := NewLevelDBMovStore(testDB)
1195                 if err := movStore.InitDBState(height, &hash); err != nil {
1196                         t.Fatalf("case %d: InitDBState error %v.", i, err)
1197                 }
1198
1199                 batch := movStore.db.NewBatch()
1200                 tradePairsCnt := make(map[string]*common.TradePair)
1201                 movStore.addOrders(batch, c.beforeOrders, tradePairsCnt)
1202                 movStore.updateTradePairs(batch, tradePairsCnt)
1203                 batch.Write()
1204
1205                 tradePairsCnt = make(map[string]*common.TradePair)
1206                 movStore.deleteOrders(batch, c.delOrders, tradePairsCnt)
1207                 movStore.updateTradePairs(batch, tradePairsCnt)
1208                 batch.Write()
1209
1210                 gotOrders, err := movStore.ListOrders(&common.Order{FromAssetID: assetID1, ToAssetID: assetID2})
1211                 if err != nil {
1212                         t.Fatalf("case %d: ListOrders error %v.", i, err)
1213                 }
1214
1215                 if !testutil.DeepEqual(gotOrders, c.wantOrders) {
1216                         t.Fatalf("case %d: got orders , gotOrders: %v, wantOrders: %v.", i, gotOrders, c.wantOrders)
1217                 }
1218
1219                 testDB.Close()
1220                 os.RemoveAll("temp")
1221         }
1222 }
1223
1224 func TestListTradePairsWithStart(t *testing.T) {
1225         cases := []struct {
1226                 desc            string
1227                 storeTradePairs map[string]*common.TradePair
1228                 query           *common.TradePair
1229                 wantTradePairs  []*common.TradePair
1230         }{
1231                 {
1232                         desc:           "empty",
1233                         query:          &common.TradePair{},
1234                         wantTradePairs: []*common.TradePair{},
1235                 },
1236                 {
1237                         desc: "query from first",
1238                         storeTradePairs: map[string]*common.TradePair{
1239                                 (&common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2}).Key(): {FromAssetID: assetID1, ToAssetID: assetID2, Count: 1},
1240                                 (&common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3}).Key(): {FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
1241                                 (&common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4}).Key(): {FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
1242                                 (&common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5}).Key(): {FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
1243                                 (&common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6}).Key(): {FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
1244                                 (&common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7}).Key(): {FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
1245                         },
1246                         query: &common.TradePair{},
1247                         wantTradePairs: []*common.TradePair{
1248                                 &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 1},
1249                                 &common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
1250                                 &common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
1251                                 &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
1252                                 &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
1253                                 &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
1254                         },
1255                 },
1256                 {
1257                         desc: "query from middle",
1258                         storeTradePairs: map[string]*common.TradePair{
1259                                 (&common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2}).Key(): {FromAssetID: assetID1, ToAssetID: assetID2, Count: 1},
1260                                 (&common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3}).Key(): {FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
1261                                 (&common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4}).Key(): {FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
1262                                 (&common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5}).Key(): {FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
1263                                 (&common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6}).Key(): {FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
1264                                 (&common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7}).Key(): {FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
1265                                 (&common.TradePair{FromAssetID: assetID6, ToAssetID: assetID8}).Key(): {FromAssetID: assetID6, ToAssetID: assetID8, Count: 7},
1266                         },
1267                         query: &common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
1268                         wantTradePairs: []*common.TradePair{
1269                                 &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
1270                                 &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
1271                                 &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
1272                                 &common.TradePair{FromAssetID: assetID6, ToAssetID: assetID8, Count: 7},
1273                         },
1274                 },
1275         }
1276
1277         initBlockHeader := &types.BlockHeader{
1278                 Height:  0,
1279                 Version: 1,
1280         }
1281
1282         height := initBlockHeader.Height
1283         hash := initBlockHeader.Hash()
1284
1285         defer os.RemoveAll("temp")
1286         for i, c := range cases {
1287                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
1288                 movStore := NewLevelDBMovStore(testDB)
1289                 if err := movStore.InitDBState(height, &hash); err != nil {
1290                         t.Fatalf("case %d: InitDBState error %v.", i, err)
1291                 }
1292
1293                 batch := movStore.db.NewBatch()
1294                 movStore.updateTradePairs(batch, c.storeTradePairs)
1295                 batch.Write()
1296
1297                 gotTradePairs, err := movStore.ListTradePairsWithStart(c.query.FromAssetID, c.query.ToAssetID)
1298                 if err != nil {
1299                         t.Fatalf("case %d: ListTradePairsWithStart error %v.", i, err)
1300                 }
1301
1302                 if !testutil.DeepEqual(gotTradePairs, c.wantTradePairs) {
1303                         t.Fatalf("case %d: got TradePairs , gotTradePairs: %v, wantTradePairs: %v.", i, gotTradePairs, c.wantTradePairs)
1304                 }
1305
1306                 testDB.Close()
1307                 os.RemoveAll("temp")
1308         }
1309 }
1310
1311 func TestUpdateTradePairs(t *testing.T) {
1312         cases := []struct {
1313                 desc             string
1314                 beforeTradePairs map[string]*common.TradePair
1315                 addTradePairs    map[string]*common.TradePair
1316                 delTradePairs    map[string]*common.TradePair
1317                 wantTradePairs   []*common.TradePair
1318         }{
1319                 {
1320                         desc: "empty",
1321                         addTradePairs: map[string]*common.TradePair{
1322                                 (&common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2}).Key(): {FromAssetID: assetID1, ToAssetID: assetID2, Count: 1},
1323                                 (&common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3}).Key(): {FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
1324                                 (&common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4}).Key(): {FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
1325                                 (&common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5}).Key(): {FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
1326                                 (&common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6}).Key(): {FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
1327                                 (&common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7}).Key(): {FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
1328                         },
1329                         wantTradePairs: []*common.TradePair{
1330                                 &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 1},
1331                                 &common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
1332                                 &common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
1333                                 &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
1334                                 &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
1335                                 &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
1336                         },
1337                 },
1338                 {
1339                         desc: "Stored data already exists",
1340                         beforeTradePairs: map[string]*common.TradePair{
1341                                 (&common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2}).Key(): {FromAssetID: assetID1, ToAssetID: assetID2, Count: 1},
1342                                 (&common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3}).Key(): {FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
1343                                 (&common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4}).Key(): {FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
1344                         },
1345                         addTradePairs: map[string]*common.TradePair{
1346                                 (&common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5}).Key(): {FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
1347                                 (&common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6}).Key(): {FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
1348                                 (&common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7}).Key(): {FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
1349                         },
1350                         wantTradePairs: []*common.TradePair{
1351                                 &common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2, Count: 1},
1352                                 &common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
1353                                 &common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
1354                                 &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
1355                                 &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
1356                                 &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
1357                         },
1358                 },
1359                 {
1360                         desc: "delete some data",
1361                         beforeTradePairs: map[string]*common.TradePair{
1362                                 (&common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2}).Key(): {FromAssetID: assetID1, ToAssetID: assetID2, Count: 1},
1363                                 (&common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3}).Key(): {FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
1364                                 (&common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4}).Key(): {FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
1365                                 (&common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5}).Key(): {FromAssetID: assetID4, ToAssetID: assetID5, Count: 4},
1366                                 (&common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6}).Key(): {FromAssetID: assetID4, ToAssetID: assetID6, Count: 5},
1367                                 (&common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7}).Key(): {FromAssetID: assetID5, ToAssetID: assetID7, Count: 6},
1368                         },
1369                         delTradePairs: map[string]*common.TradePair{
1370                                 (&common.TradePair{FromAssetID: assetID1, ToAssetID: assetID2}).Key(): {FromAssetID: assetID1, ToAssetID: assetID2, Count: -1},
1371                                 (&common.TradePair{FromAssetID: assetID4, ToAssetID: assetID5}).Key(): {FromAssetID: assetID4, ToAssetID: assetID5, Count: -4},
1372                                 (&common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6}).Key(): {FromAssetID: assetID4, ToAssetID: assetID6, Count: -2},
1373                                 (&common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7}).Key(): {FromAssetID: assetID5, ToAssetID: assetID7, Count: -4},
1374                         },
1375                         wantTradePairs: []*common.TradePair{
1376                                 &common.TradePair{FromAssetID: assetID2, ToAssetID: assetID3, Count: 2},
1377                                 &common.TradePair{FromAssetID: assetID3, ToAssetID: assetID4, Count: 3},
1378                                 &common.TradePair{FromAssetID: assetID4, ToAssetID: assetID6, Count: 3},
1379                                 &common.TradePair{FromAssetID: assetID5, ToAssetID: assetID7, Count: 2},
1380                         },
1381                 },
1382         }
1383
1384         initBlockHeader := &types.BlockHeader{
1385                 Height:  0,
1386                 Version: 1,
1387         }
1388
1389         height := initBlockHeader.Height
1390         hash := initBlockHeader.Hash()
1391
1392         defer os.RemoveAll("temp")
1393         for i, c := range cases {
1394                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
1395                 movStore := NewLevelDBMovStore(testDB)
1396                 if err := movStore.InitDBState(height, &hash); err != nil {
1397                         t.Fatalf("case %d: InitDBState error %v.", i, err)
1398                 }
1399
1400                 batch := movStore.db.NewBatch()
1401                 movStore.updateTradePairs(batch, c.beforeTradePairs)
1402                 batch.Write()
1403
1404                 movStore.updateTradePairs(batch, c.addTradePairs)
1405                 movStore.updateTradePairs(batch, c.delTradePairs)
1406                 batch.Write()
1407
1408                 gotTradePairs, err := movStore.ListTradePairsWithStart(nil, nil)
1409                 if err != nil {
1410                         t.Fatalf("case %d: ListTradePairsWithStart error %v.", i, err)
1411                 }
1412
1413                 if !testutil.DeepEqual(gotTradePairs, c.wantTradePairs) {
1414                         t.Fatalf("case %d: got TradePairs , gotTradePairs: %v, wantTradePairs: %v.", i, gotTradePairs, c.wantTradePairs)
1415                 }
1416
1417                 testDB.Close()
1418                 os.RemoveAll("temp")
1419         }
1420 }
1421
1422 func TestCheckMovDatabaseState(t *testing.T) {
1423         cases := []struct {
1424                 desc           string
1425                 beforeDBStatus *common.MovDatabaseState
1426                 blockHeader    *types.BlockHeader
1427                 err            error
1428         }{
1429                 {
1430                         desc:           "attach Block",
1431                         beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
1432                         blockHeader:    &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
1433                         err:            nil,
1434                 },
1435                 {
1436                         desc:           "error attach Block",
1437                         beforeDBStatus: &common.MovDatabaseState{Height: 1, Hash: &bc.Hash{V0: 14213576368347360351, V1: 16287398171800437029, V2: 9513543230620030445, V3: 8534035697182508177}},
1438                         blockHeader:    &types.BlockHeader{Height: 2, PreviousBlockHash: bc.Hash{}},
1439                         err:            errors.New("the status of the block is inconsistent with that of mov-database"),
1440                 },
1441
1442                 {
1443                         desc:           "detach Block",
1444                         beforeDBStatus: &common.MovDatabaseState{Height: 5, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
1445                         blockHeader:    &types.BlockHeader{Height: 4},
1446                         err:            nil,
1447                 },
1448                 {
1449                         desc:           "error detach Block",
1450                         beforeDBStatus: &common.MovDatabaseState{Height: 5, Hash: &bc.Hash{V0: 3724755213446347384, V1: 158878632373345042, V2: 18283800951484248781, V3: 7520797730449067221}},
1451                         blockHeader:    &types.BlockHeader{Height: 3},
1452                         err:            errors.New("the status of the block is inconsistent with that of mov-database"),
1453                 },
1454         }
1455
1456         initBlockHeader := &types.BlockHeader{
1457                 Height:  0,
1458                 Version: 1,
1459         }
1460
1461         height := initBlockHeader.Height
1462         hash := initBlockHeader.Hash()
1463
1464         defer os.RemoveAll("temp")
1465         for i, c := range cases {
1466                 testDB := dbm.NewDB("testdb", "leveldb", "temp")
1467                 movStore := NewLevelDBMovStore(testDB)
1468                 if err := movStore.InitDBState(height, &hash); err != nil {
1469                         t.Fatalf("case %d: InitDBState error %v.", i, err)
1470                 }
1471
1472                 batch := movStore.db.NewBatch()
1473                 movStore.saveMovDatabaseState(batch, c.beforeDBStatus)
1474                 batch.Write()
1475
1476                 if err := movStore.checkMovDatabaseState(c.blockHeader); c.err != nil && c.err.Error() != err.Error() {
1477                         t.Fatalf("case %d: checkMovDatabaseState error %v.", i, err)
1478                 }
1479
1480                 testDB.Close()
1481                 os.RemoveAll("temp")
1482         }
1483
1484 }