OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / btcsuite / btcd / blockchain / mediantime_test.go
1 // Copyright (c) 2013-2017 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
4
5 package blockchain
6
7 import (
8         "strconv"
9         "testing"
10         "time"
11 )
12
13 // TestMedianTime tests the medianTime implementation.
14 func TestMedianTime(t *testing.T) {
15         tests := []struct {
16                 in         []int64
17                 wantOffset int64
18                 useDupID   bool
19         }{
20                 // Not enough samples must result in an offset of 0.
21                 {in: []int64{1}, wantOffset: 0},
22                 {in: []int64{1, 2}, wantOffset: 0},
23                 {in: []int64{1, 2, 3}, wantOffset: 0},
24                 {in: []int64{1, 2, 3, 4}, wantOffset: 0},
25
26                 // Various number of entries.  The expected offset is only
27                 // updated on odd number of elements.
28                 {in: []int64{-13, 57, -4, -23, -12}, wantOffset: -12},
29                 {in: []int64{55, -13, 61, -52, 39, 55}, wantOffset: 39},
30                 {in: []int64{-62, -58, -30, -62, 51, -30, 15}, wantOffset: -30},
31                 {in: []int64{29, -47, 39, 54, 42, 41, 8, -33}, wantOffset: 39},
32                 {in: []int64{37, 54, 9, -21, -56, -36, 5, -11, -39}, wantOffset: -11},
33                 {in: []int64{57, -28, 25, -39, 9, 63, -16, 19, -60, 25}, wantOffset: 9},
34                 {in: []int64{-5, -4, -3, -2, -1}, wantOffset: -3, useDupID: true},
35
36                 // The offset stops being updated once the max number of entries
37                 // has been reached.  This is actually a bug from Bitcoin Core,
38                 // but since the time is ultimately used as a part of the
39                 // consensus rules, it must be mirrored.
40                 {in: []int64{-67, 67, -50, 24, 63, 17, 58, -14, 5, -32, -52}, wantOffset: 17},
41                 {in: []int64{-67, 67, -50, 24, 63, 17, 58, -14, 5, -32, -52, 45}, wantOffset: 17},
42                 {in: []int64{-67, 67, -50, 24, 63, 17, 58, -14, 5, -32, -52, 45, 4}, wantOffset: 17},
43
44                 // Offsets that are too far away from the local time should
45                 // be ignored.
46                 {in: []int64{-4201, 4202, -4203, 4204, -4205}, wantOffset: 0},
47
48                 // Excerise the condition where the median offset is greater
49                 // than the max allowed adjustment, but there is at least one
50                 // sample that is close enough to the current time to avoid
51                 // triggering a warning about an invalid local clock.
52                 {in: []int64{4201, 4202, 4203, 4204, -299}, wantOffset: 0},
53         }
54
55         // Modify the max number of allowed median time entries for these tests.
56         maxMedianTimeEntries = 10
57         defer func() { maxMedianTimeEntries = 200 }()
58
59         for i, test := range tests {
60                 filter := NewMedianTime()
61                 for j, offset := range test.in {
62                         id := strconv.Itoa(j)
63                         now := time.Unix(time.Now().Unix(), 0)
64                         tOffset := now.Add(time.Duration(offset) * time.Second)
65                         filter.AddTimeSample(id, tOffset)
66
67                         // Ensure the duplicate IDs are ignored.
68                         if test.useDupID {
69                                 // Modify the offsets to ensure the final median
70                                 // would be different if the duplicate is added.
71                                 tOffset = tOffset.Add(time.Duration(offset) *
72                                         time.Second)
73                                 filter.AddTimeSample(id, tOffset)
74                         }
75                 }
76
77                 // Since it is possible that the time.Now call in AddTimeSample
78                 // and the time.Now calls here in the tests will be off by one
79                 // second, allow a fudge factor to compensate.
80                 gotOffset := filter.Offset()
81                 wantOffset := time.Duration(test.wantOffset) * time.Second
82                 wantOffset2 := time.Duration(test.wantOffset-1) * time.Second
83                 if gotOffset != wantOffset && gotOffset != wantOffset2 {
84                         t.Errorf("Offset #%d: unexpected offset -- got %v, "+
85                                 "want %v or %v", i, gotOffset, wantOffset,
86                                 wantOffset2)
87                         continue
88                 }
89
90                 // Since it is possible that the time.Now call in AdjustedTime
91                 // and the time.Now call here in the tests will be off by one
92                 // second, allow a fudge factor to compensate.
93                 adjustedTime := filter.AdjustedTime()
94                 now := time.Unix(time.Now().Unix(), 0)
95                 wantTime := now.Add(filter.Offset())
96                 wantTime2 := now.Add(filter.Offset() - time.Second)
97                 if !adjustedTime.Equal(wantTime) && !adjustedTime.Equal(wantTime2) {
98                         t.Errorf("AdjustedTime #%d: unexpected result -- got %v, "+
99                                 "want %v or %v", i, adjustedTime, wantTime,
100                                 wantTime2)
101                         continue
102                 }
103         }
104 }