dcrd/internal/progresslog/logger_test.go
Dave Collins ae4281bcfc
multi: Add chain verify progress percentage.
This modifies blockchain, progresslog, and netsync to provide a progress
percentage when logging the main chain verification process.

A new method is added to blockchain that determines the verification
progress of the current best chain based on how far along it towards the
best known header and blockchain is also modified to log the
verification progress in the initial chain state message when the
blockchain is first loaded.

In addition, the progess logger is modified to log the verification
progress instead of the timestamp of the last block and the netsync code
is updated to make use of the new verification progress func per above.

Finally, the netsync code now determines when the chain is considered
current and logs new blocks as they are connected along with their hash
and additional details.  This provides a cleaner distinction between the
initial verification and catchup phase and steady state operation.
2021-01-21 23:30:35 -06:00

229 lines
6.7 KiB
Go

// Copyright (c) 2021 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package progresslog
import (
"io/ioutil"
"reflect"
"testing"
"time"
"github.com/decred/dcrd/wire"
"github.com/decred/slog"
)
var (
backendLog = slog.NewBackend(ioutil.Discard)
testLog = backendLog.Logger("TEST")
)
// TestLogProgress ensures the logging functionality works as expected via a
// test logger.
func TestLogProgress(t *testing.T) {
testBlocks := []wire.MsgBlock{{
Header: wire.BlockHeader{
Version: 1,
Height: 100000,
Timestamp: time.Unix(1293623863, 0), // 2010-12-29 11:57:43 +0000 UTC
Voters: 2,
Revocations: 1,
FreshStake: 4,
},
Transactions: make([]*wire.MsgTx, 4),
STransactions: nil,
}, {
Header: wire.BlockHeader{
Version: 1,
Height: 100001,
Timestamp: time.Unix(1293624163, 0), // 2010-12-29 12:02:43 +0000 UTC
Voters: 3,
Revocations: 2,
FreshStake: 2,
},
Transactions: make([]*wire.MsgTx, 2),
STransactions: nil,
}, {
Header: wire.BlockHeader{
Version: 1,
Height: 100002,
Timestamp: time.Unix(1293624463, 0), // 2010-12-29 12:07:43 +0000 UTC
Voters: 1,
Revocations: 3,
FreshStake: 1,
},
Transactions: make([]*wire.MsgTx, 3),
STransactions: nil,
}}
tests := []struct {
name string
reset bool
inputBlock *wire.MsgBlock
forceLog bool
inputLastLogTime time.Time
wantReceivedBlocks uint64
wantReceivedTxns uint64
wantReceivedVotes uint64
wantReceivedRevokes uint64
wantReceivedTickets uint64
}{{
name: "round 1, block 0, last log time < 10 secs ago, not forced",
inputBlock: &testBlocks[0],
forceLog: false,
inputLastLogTime: time.Now(),
wantReceivedBlocks: 1,
wantReceivedTxns: 4,
wantReceivedVotes: 2,
wantReceivedRevokes: 1,
wantReceivedTickets: 4,
}, {
name: "round 1, block 1, last log time < 10 secs ago, not forced",
inputBlock: &testBlocks[1],
forceLog: false,
inputLastLogTime: time.Now(),
wantReceivedBlocks: 2,
wantReceivedTxns: 6,
wantReceivedVotes: 5,
wantReceivedRevokes: 3,
wantReceivedTickets: 6,
}, {
name: "round 1, block 2, last log time < 10 secs ago, forced",
inputBlock: &testBlocks[2],
forceLog: true,
inputLastLogTime: time.Now(),
wantReceivedBlocks: 0,
wantReceivedTxns: 0,
wantReceivedVotes: 0,
wantReceivedRevokes: 0,
wantReceivedTickets: 0,
}, {
name: "round 2, block 0, last log time < 10 secs ago, not forced",
reset: true,
inputBlock: &testBlocks[0],
forceLog: false,
inputLastLogTime: time.Now(),
wantReceivedBlocks: 1,
wantReceivedTxns: 4,
wantReceivedVotes: 2,
wantReceivedRevokes: 1,
wantReceivedTickets: 4,
}, {
name: "round 2, block 1, last log time > 10 secs ago, not forced",
inputBlock: &testBlocks[1],
forceLog: false,
inputLastLogTime: time.Now().Add(-11 * time.Second),
wantReceivedBlocks: 0,
wantReceivedTxns: 0,
wantReceivedVotes: 0,
wantReceivedRevokes: 0,
wantReceivedTickets: 0,
}, {
name: "round 2, block 2, last log time > 10 secs ago, forced",
inputBlock: &testBlocks[2],
forceLog: true,
inputLastLogTime: time.Now().Add(-11 * time.Second),
wantReceivedBlocks: 0,
wantReceivedTxns: 0,
wantReceivedVotes: 0,
wantReceivedRevokes: 0,
wantReceivedTickets: 0,
}}
progressFn := func() float64 { return 0.0 }
progressLogger := New("Wrote", testLog)
for _, test := range tests {
if test.reset {
progressLogger = New("Wrote", testLog)
}
progressLogger.SetLastLogTime(test.inputLastLogTime)
progressLogger.LogProgress(test.inputBlock, test.forceLog, progressFn)
wantBlockProgressLogger := &Logger{
receivedBlocks: test.wantReceivedBlocks,
receivedTxns: test.wantReceivedTxns,
receivedVotes: test.wantReceivedVotes,
receivedRevokes: test.wantReceivedRevokes,
receivedTickets: test.wantReceivedTickets,
lastLogTime: progressLogger.lastLogTime,
progressAction: progressLogger.progressAction,
subsystemLogger: progressLogger.subsystemLogger,
}
if !reflect.DeepEqual(progressLogger, wantBlockProgressLogger) {
t.Errorf("%s:\nwant: %+v\ngot: %+v\n", test.name,
wantBlockProgressLogger, progressLogger)
}
}
}
// TestLogHeaderProgress ensures the logging functionality for headers works as
// expected via a test logger.
func TestLogHeaderProgress(t *testing.T) {
tests := []struct {
name string
reset bool
numHeaders uint64
forceLog bool
lastLogTime time.Time
wantReceivedHeaders uint64
}{{
name: "round 1, batch 1, last log time < 10 secs ago, not forced",
numHeaders: 35500,
forceLog: false,
lastLogTime: time.Now(),
wantReceivedHeaders: 35500,
}, {
name: "round 1, batch 2, last log time < 10 secs ago, not forced",
numHeaders: 40000,
forceLog: false,
lastLogTime: time.Now(),
wantReceivedHeaders: 75500,
}, {
name: "round 1, batch 3, last log time < 10 secs ago, not forced",
numHeaders: 66500,
forceLog: false,
lastLogTime: time.Now(),
wantReceivedHeaders: 142000,
}, {
name: "round 2, batch 1, last log time < 10 secs ago, not forced",
reset: true,
numHeaders: 40000,
forceLog: false,
lastLogTime: time.Now(),
wantReceivedHeaders: 40000,
}, {
name: "round 2, batch 2, last log time > 10 secs ago, not forced",
numHeaders: 66500,
forceLog: false,
lastLogTime: time.Now().Add(-11 * time.Second),
wantReceivedHeaders: 0,
}, {
name: "round 2, batch 1, last log time < 10 secs ago, forced",
reset: true,
numHeaders: 54330,
forceLog: true,
lastLogTime: time.Now(),
wantReceivedHeaders: 0,
}}
progressFn := func() float64 { return 0.0 }
logger := New("Wrote", testLog)
for _, test := range tests {
if test.reset {
logger = New("Wrote", testLog)
}
logger.SetLastLogTime(test.lastLogTime)
logger.LogHeaderProgress(test.numHeaders, test.forceLog, progressFn)
want := &Logger{
subsystemLogger: logger.subsystemLogger,
progressAction: logger.progressAction,
lastLogTime: logger.lastLogTime,
receivedHeaders: test.wantReceivedHeaders,
}
if !reflect.DeepEqual(logger, want) {
t.Errorf("%s:\nwant: %+v\ngot: %+v\n", test.name, want, logger)
}
}
}