lnd.xprv/lntest/wait/wait.go
Conner Fromknecht 396a978cec
lntest+wait: replace sleeps in assertAmountSent
This commit constructs a helper closure assertAmountSent that can be
reused by other functions. The closure returns an error so that it can
be used with wait.NoError or the new wait.InvariantNoError. The latter
is added since the predicate could otherwise pass immediately for the
sphinx_replay_persistence tests, but change shortly after. It also
rounds out the wait package so that we offer all combinations of
predicate and no-error style waits.
2019-12-18 23:57:12 -08:00

99 lines
2.5 KiB
Go

package wait
import (
"fmt"
"time"
)
// Predicate is a helper test function that will wait for a timeout period of
// time until the passed predicate returns true. This function is helpful as
// timing doesn't always line up well when running integration tests with
// several running lnd nodes. This function gives callers a way to assert that
// some property is upheld within a particular time frame.
func Predicate(pred func() bool, timeout time.Duration) error {
const pollInterval = 20 * time.Millisecond
exitTimer := time.After(timeout)
for {
<-time.After(pollInterval)
select {
case <-exitTimer:
return fmt.Errorf("predicate not satisfied after time out")
default:
}
if pred() {
return nil
}
}
}
// NoError is a wrapper around Predicate that waits for the passed method f to
// execute without error, and returns the last error encountered if this doesn't
// happen within the timeout.
func NoError(f func() error, timeout time.Duration) error {
var predErr error
pred := func() bool {
if err := f(); err != nil {
predErr = err
return false
}
return true
}
// If f() doesn't succeed within the timeout, return the last
// encountered error.
if err := Predicate(pred, timeout); err != nil {
return predErr
}
return nil
}
// Invariant is a helper test function that will wait for a timeout period of
// time, verifying that a statement remains true for the entire duration. This
// function is helpful as timing doesn't always line up well when running
// integration tests with several running lnd nodes. This function gives callers
// a way to assert that some property is maintained over a particular time
// frame.
func Invariant(statement func() bool, timeout time.Duration) error {
const pollInterval = 20 * time.Millisecond
exitTimer := time.After(timeout)
for {
<-time.After(pollInterval)
// Fail if the invariant is broken while polling.
if !statement() {
return fmt.Errorf("invariant broken before time out")
}
select {
case <-exitTimer:
return nil
default:
}
}
}
// InvariantNoError is a wrapper around Invariant that waits out the duration
// specified by timeout. It fails if the predicate ever returns an error during
// that time.
func InvariantNoError(f func() error, timeout time.Duration) error {
var predErr error
pred := func() bool {
if err := f(); err != nil {
predErr = err
return false
}
return true
}
if err := Invariant(pred, timeout); err != nil {
return predErr
}
return nil
}