OSDN Git Service

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