Refactor mock Sleep, add mock Now time function

Instead of the Sleep function pointer being a standalong global
variable, move it into a new Time struct, and add a Now function
pointer, so that time.Now() can be mocked. Time.Now() isn't used yet.
This will be cleaner if we need to mock more time-related functions in
the future.
This commit is contained in:
Larry Ruane 2021-07-25 07:47:07 -06:00 committed by Larry Ruane
parent 4f00783f48
commit 6357f7f15b
4 changed files with 25 additions and 14 deletions

View File

@ -381,8 +381,9 @@ func init() {
logrus.RegisterExitHandler(onexit)
// Indirect function for test mocking (so unit tests can talk to stub functions)
common.Sleep = time.Sleep
// Indirect functions for test mocking (so unit tests can talk to stub functions)
common.Time.Sleep = time.Sleep
common.Time.Now = time.Now
}
// initConfig reads in config file and ENV variables if set.

View File

@ -53,10 +53,16 @@ type Options struct {
// in unit tests it points to a function to mock RPCs to zcashd.
var RawRequest func(method string, params []json.RawMessage) (json.RawMessage, error)
// Sleep allows a request to time.Sleep() to be mocked for testing;
// in production, it points to the standard library time.Sleep();
// in unit tests it points to a mock function.
var Sleep func(d time.Duration)
// Time allows time-related functions to be mocked for testing,
// so that tests can be deterministic and so they don't require
// real time to elapse. In production, these point to the standard
// library `time` functions; in unit tests they point to mock
// functions (set by the specific test as required).
// More functions can be added later.
var Time struct {
Sleep func(d time.Duration)
Now func() time.Time
}
// Log as a global variable simplifies logging
var Log *logrus.Entry
@ -163,7 +169,7 @@ func FirstRPC() {
"error": rpcErr.Error(),
"retry": retryCount,
}).Warn("error with getblockchaininfo rpc, retrying...")
Sleep(time.Duration(10+retryCount*5) * time.Second) // backoff
Time.Sleep(time.Duration(10+retryCount*5) * time.Second) // backoff
}
}
@ -312,7 +318,7 @@ func BlockIngestor(c *BlockCache, rep int) {
}
// Delay then retry the same height.
c.Sync()
Sleep(10 * time.Second)
Time.Sleep(10 * time.Second)
wait = true
continue
}
@ -323,7 +329,7 @@ func BlockIngestor(c *BlockCache, rep int) {
Log.Info("Waiting for zcashd height to reach Sapling activation height ",
"(", c.GetFirstHeight(), ")...")
reorgCount = 0
Sleep(20 * time.Second)
Time.Sleep(20 * time.Second)
continue
}
if wait {
@ -333,7 +339,7 @@ func BlockIngestor(c *BlockCache, rep int) {
Log.Info("Ingestor waiting for block: ", height)
lastHeightLogged = height - 1
}
Sleep(2 * time.Second)
Time.Sleep(2 * time.Second)
wait = false
continue
}

View File

@ -77,6 +77,10 @@ func sleepStub(d time.Duration) {
sleepCount++
sleepDuration += d
}
func nowStub() time.Time {
start := time.Time{}
return start.Add(sleepDuration)
}
// ------------------------------------------ GetLightdInfo()
@ -110,7 +114,7 @@ func getLightdInfoStub(method string, params []json.RawMessage) (json.RawMessage
func TestGetLightdInfo(t *testing.T) {
testT = t
RawRequest = getLightdInfoStub
Sleep = sleepStub
Time.Sleep = sleepStub
// This calls the getblockchaininfo rpc just to establish connectivity with zcashd
FirstRPC()
@ -270,7 +274,7 @@ func getblockStub(method string, params []json.RawMessage) (json.RawMessage, err
func TestBlockIngestor(t *testing.T) {
testT = t
RawRequest = getblockStub
Sleep = sleepStub
Time.Sleep = sleepStub
os.RemoveAll(unitTestPath)
testcache := NewBlockCache(unitTestPath, unitTestChain, 380640, false)
BlockIngestor(testcache, 11)

View File

@ -64,7 +64,7 @@ func GetMempool(sendToClient func(*walletrpc.RawTransaction) error) error {
g_lock.Unlock()
return err
}
g_lastTime = time.Now()
g_lastTime = Time.Now()
}
// Send transactions we haven't sent yet, best to not do so while
// holding the mutex, since this call may get flow-controlled.
@ -76,7 +76,7 @@ func GetMempool(sendToClient func(*walletrpc.RawTransaction) error) error {
return err
}
}
time.Sleep(200 * time.Millisecond)
Time.Sleep(200 * time.Millisecond)
g_lock.Lock()
if g_lastBlockChainInfo.BestBlockHash != stayHash {
break