// 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" "reflect" "testing" "time" "github.com/decred/dcrd/wire" "github.com/decred/slog" ) var ( backendLog = slog.NewBackend(io.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) } } }