OSDN Git Service

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