e02fbcf5a1
Putting the test code in the same package makes it easier for forks since they don't have to change the import paths as much and it also gets rid of the need for internal_test.go to bridge. While here, remove the reorganization test since it is much better handled by the full block tests and is no longer needed and do some light cleanup on a few other tests. The full block tests had to remain in the separate test package since it is a circular dependency otherwise. This did require duplicating some of the chain setup code, but given the other benefits this is acceptable.
104 lines
3.8 KiB
Go
104 lines
3.8 KiB
Go
// Copyright (c) 2013-2017 The btcsuite developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package blockchain
|
|
|
|
import (
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// TestMedianTime tests the medianTime implementation.
|
|
func TestMedianTime(t *testing.T) {
|
|
tests := []struct {
|
|
in []int64
|
|
wantOffset int64
|
|
useDupID bool
|
|
}{
|
|
// Not enough samples must result in an offset of 0.
|
|
{in: []int64{1}, wantOffset: 0},
|
|
{in: []int64{1, 2}, wantOffset: 0},
|
|
{in: []int64{1, 2, 3}, wantOffset: 0},
|
|
{in: []int64{1, 2, 3, 4}, wantOffset: 0},
|
|
|
|
// Various number of entries. The expected offset is only
|
|
// updated on odd number of elements.
|
|
{in: []int64{-13, 57, -4, -23, -12}, wantOffset: -12},
|
|
{in: []int64{55, -13, 61, -52, 39, 55}, wantOffset: 39},
|
|
{in: []int64{-62, -58, -30, -62, 51, -30, 15}, wantOffset: -30},
|
|
{in: []int64{29, -47, 39, 54, 42, 41, 8, -33}, wantOffset: 39},
|
|
{in: []int64{37, 54, 9, -21, -56, -36, 5, -11, -39}, wantOffset: -11},
|
|
{in: []int64{57, -28, 25, -39, 9, 63, -16, 19, -60, 25}, wantOffset: 9},
|
|
{in: []int64{-5, -4, -3, -2, -1}, wantOffset: -3, useDupID: true},
|
|
|
|
// The offset stops being updated once the max number of entries
|
|
// has been reached. This is actually a bug from Bitcoin Core,
|
|
// but since the time is ultimately used as a part of the
|
|
// consensus rules, it must be mirrored.
|
|
{in: []int64{-67, 67, -50, 24, 63, 17, 58, -14, 5, -32, -52}, wantOffset: 17},
|
|
{in: []int64{-67, 67, -50, 24, 63, 17, 58, -14, 5, -32, -52, 45}, wantOffset: 17},
|
|
{in: []int64{-67, 67, -50, 24, 63, 17, 58, -14, 5, -32, -52, 45, 4}, wantOffset: 17},
|
|
|
|
// Offsets that are too far away from the local time should
|
|
// be ignored.
|
|
{in: []int64{-4201, 4202, -4203, 4204, -4205}, wantOffset: 0},
|
|
|
|
// Excerise the condition where the median offset is greater
|
|
// than the max allowed adjustment, but there is at least one
|
|
// sample that is close enough to the current time to avoid
|
|
// triggering a warning about an invalid local clock.
|
|
{in: []int64{4201, 4202, 4203, 4204, -299}, wantOffset: 0},
|
|
}
|
|
|
|
// Modify the max number of allowed median time entries for these tests.
|
|
maxMedianTimeEntries = 10
|
|
defer func() { maxMedianTimeEntries = 200 }()
|
|
|
|
for i, test := range tests {
|
|
filter := NewMedianTime()
|
|
for j, offset := range test.in {
|
|
id := strconv.Itoa(j)
|
|
now := time.Unix(time.Now().Unix(), 0)
|
|
tOffset := now.Add(time.Duration(offset) * time.Second)
|
|
filter.AddTimeSample(id, tOffset)
|
|
|
|
// Ensure the duplicate IDs are ignored.
|
|
if test.useDupID {
|
|
// Modify the offsets to ensure the final median
|
|
// would be different if the duplicate is added.
|
|
tOffset = tOffset.Add(time.Duration(offset) *
|
|
time.Second)
|
|
filter.AddTimeSample(id, tOffset)
|
|
}
|
|
}
|
|
|
|
// Since it is possible that the time.Now call in AddTimeSample
|
|
// and the time.Now calls here in the tests will be off by one
|
|
// second, allow a fudge factor to compensate.
|
|
gotOffset := filter.Offset()
|
|
wantOffset := time.Duration(test.wantOffset) * time.Second
|
|
wantOffset2 := time.Duration(test.wantOffset-1) * time.Second
|
|
if gotOffset != wantOffset && gotOffset != wantOffset2 {
|
|
t.Errorf("Offset #%d: unexpected offset -- got %v, "+
|
|
"want %v or %v", i, gotOffset, wantOffset,
|
|
wantOffset2)
|
|
continue
|
|
}
|
|
|
|
// Since it is possible that the time.Now call in AdjustedTime
|
|
// and the time.Now call here in the tests will be off by one
|
|
// second, allow a fudge factor to compensate.
|
|
adjustedTime := filter.AdjustedTime()
|
|
now := time.Unix(time.Now().Unix(), 0)
|
|
wantTime := now.Add(filter.Offset())
|
|
wantTime2 := now.Add(filter.Offset() - time.Second)
|
|
if !adjustedTime.Equal(wantTime) && !adjustedTime.Equal(wantTime2) {
|
|
t.Errorf("AdjustedTime #%d: unexpected result -- got %v, "+
|
|
"want %v or %v", i, adjustedTime, wantTime,
|
|
wantTime2)
|
|
continue
|
|
}
|
|
}
|
|
}
|