github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/blockchain/mediantime_test.go (about)

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