Commit 18524dbd authored by Joshua Gutow's avatar Joshua Gutow

txmgr: Fake sendState clock in tests

parent cd2975c6
...@@ -17,6 +17,7 @@ import ( ...@@ -17,6 +17,7 @@ import (
type SendState struct { type SendState struct {
minedTxs map[common.Hash]struct{} minedTxs map[common.Hash]struct{}
mu sync.RWMutex mu sync.RWMutex
now func() time.Time
// Config // Config
nonceTooLowCount uint64 nonceTooLowCount uint64
...@@ -27,9 +28,8 @@ type SendState struct { ...@@ -27,9 +28,8 @@ type SendState struct {
safeAbortNonceTooLowCount uint64 // nonce too low error safeAbortNonceTooLowCount uint64 // nonce too low error
} }
// NewSendState parameterizes a new SendState from the passed // NewSendStateWithNow creates a new send state with the provided clock.
// safeAbortNonceTooLowCount. func NewSendStateWithNow(safeAbortNonceTooLowCount uint64, unableToSendTimeout time.Duration, now func() time.Time) *SendState {
func NewSendState(safeAbortNonceTooLowCount uint64, unableToSendTimeout time.Duration) *SendState {
if safeAbortNonceTooLowCount == 0 { if safeAbortNonceTooLowCount == 0 {
panic("txmgr: safeAbortNonceTooLowCount cannot be zero") panic("txmgr: safeAbortNonceTooLowCount cannot be zero")
} }
...@@ -37,10 +37,16 @@ func NewSendState(safeAbortNonceTooLowCount uint64, unableToSendTimeout time.Dur ...@@ -37,10 +37,16 @@ func NewSendState(safeAbortNonceTooLowCount uint64, unableToSendTimeout time.Dur
return &SendState{ return &SendState{
minedTxs: make(map[common.Hash]struct{}), minedTxs: make(map[common.Hash]struct{}),
safeAbortNonceTooLowCount: safeAbortNonceTooLowCount, safeAbortNonceTooLowCount: safeAbortNonceTooLowCount,
txInMempoolDeadline: time.Now().Add(unableToSendTimeout), txInMempoolDeadline: now().Add(unableToSendTimeout),
now: now,
} }
} }
// NewSendState creates a new send state
func NewSendState(safeAbortNonceTooLowCount uint64, unableToSendTimeout time.Duration) *SendState {
return NewSendStateWithNow(safeAbortNonceTooLowCount, unableToSendTimeout, time.Now)
}
// ProcessSendError should be invoked with the error returned for each // ProcessSendError should be invoked with the error returned for each
// publication. It is safe to call this method with nil or arbitrary errors. // publication. It is safe to call this method with nil or arbitrary errors.
func (s *SendState) ProcessSendError(err error) { func (s *SendState) ProcessSendError(err error) {
...@@ -100,7 +106,7 @@ func (s *SendState) ShouldAbortImmediately() bool { ...@@ -100,7 +106,7 @@ func (s *SendState) ShouldAbortImmediately() bool {
// If we have exceeded the nonce too low count, abort // If we have exceeded the nonce too low count, abort
if s.nonceTooLowCount >= s.safeAbortNonceTooLowCount || if s.nonceTooLowCount >= s.safeAbortNonceTooLowCount ||
// If we have not published a transaction in the allotted time, abort // If we have not published a transaction in the allotted time, abort
(s.successFullPublishCount == 0 && time.Now().After(s.txInMempoolDeadline)) { (s.successFullPublishCount == 0 && s.now().After(s.txInMempoolDeadline)) {
return true return true
} }
......
...@@ -19,11 +19,11 @@ var ( ...@@ -19,11 +19,11 @@ var (
const testSafeAbortNonceTooLowCount = 3 const testSafeAbortNonceTooLowCount = 3
func newSendState() *txmgr.SendState { func newSendState() *txmgr.SendState {
return newSendStateWithTimeout(time.Hour) return newSendStateWithTimeout(time.Hour, time.Now)
} }
func newSendStateWithTimeout(t time.Duration) *txmgr.SendState { func newSendStateWithTimeout(t time.Duration, now func() time.Time) *txmgr.SendState {
return txmgr.NewSendState(testSafeAbortNonceTooLowCount, t) return txmgr.NewSendStateWithNow(testSafeAbortNonceTooLowCount, t, now)
} }
func processNSendErrors(sendState *txmgr.SendState, err error, n int) { func processNSendErrors(sendState *txmgr.SendState, err error, n int) {
...@@ -166,19 +166,26 @@ func TestSendStateIsNotWaitingForConfirmationAfterTxUnmined(t *testing.T) { ...@@ -166,19 +166,26 @@ func TestSendStateIsNotWaitingForConfirmationAfterTxUnmined(t *testing.T) {
require.False(t, sendState.IsWaitingForConfirmation()) require.False(t, sendState.IsWaitingForConfirmation())
} }
func stepClock(step time.Duration) func() time.Time {
i := 0
return func() time.Time {
var start time.Time
i += 1
return start.Add(time.Duration(i) * step)
}
}
// TestSendStateTimeoutAbort ensure that this will abort if it passes the tx pool timeout // TestSendStateTimeoutAbort ensure that this will abort if it passes the tx pool timeout
// when no successful transactions have been recorded // when no successful transactions have been recorded
func TestSendStateTimeoutAbort(t *testing.T) { func TestSendStateTimeoutAbort(t *testing.T) {
sendState := newSendStateWithTimeout(10 * time.Millisecond) sendState := newSendStateWithTimeout(10*time.Millisecond, stepClock(20*time.Millisecond))
time.Sleep(20 * time.Millisecond)
require.True(t, sendState.ShouldAbortImmediately(), "Should abort after timing out") require.True(t, sendState.ShouldAbortImmediately(), "Should abort after timing out")
} }
// TestSendStateNoTimeoutAbortIfPublishedTx ensure that this will not abort if there is // TestSendStateNoTimeoutAbortIfPublishedTx ensure that this will not abort if there is
// a successful transaction send. // a successful transaction send.
func TestSendStateNoTimeoutAbortIfPublishedTx(t *testing.T) { func TestSendStateNoTimeoutAbortIfPublishedTx(t *testing.T) {
sendState := newSendStateWithTimeout(10 * time.Millisecond) sendState := newSendStateWithTimeout(10*time.Millisecond, stepClock(20*time.Millisecond))
sendState.ProcessSendError(nil) sendState.ProcessSendError(nil)
time.Sleep(20 * time.Millisecond)
require.False(t, sendState.ShouldAbortImmediately(), "Should not abort if published transcation successfully") require.False(t, sendState.ShouldAbortImmediately(), "Should not abort if published transcation successfully")
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment