github.com/decred/dcrlnd@v0.7.6/lntest/wait/wait.go (about) 1 package wait 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 // PollInterval is a constant specifying a 200 ms interval. 9 const PollInterval = 200 * time.Millisecond 10 11 // Predicate is a helper test function that will wait for a timeout period of 12 // time until the passed predicate returns true. This function is helpful as 13 // timing doesn't always line up well when running integration tests with 14 // several running lnd nodes. This function gives callers a way to assert that 15 // some property is upheld within a particular time frame. 16 func Predicate(pred func() bool, timeout time.Duration) error { 17 exitTimer := time.After(timeout) 18 for { 19 <-time.After(PollInterval) 20 21 select { 22 case <-exitTimer: 23 return fmt.Errorf("predicate not satisfied after time out") 24 default: 25 } 26 27 if pred() { 28 return nil 29 } 30 } 31 } 32 33 // NoError is a wrapper around Predicate that waits for the passed method f to 34 // execute without error, and returns the last error encountered if this doesn't 35 // happen within the timeout. 36 func NoError(f func() error, timeout time.Duration) error { 37 var predErr error 38 pred := func() bool { 39 if err := f(); err != nil { 40 predErr = err 41 return false 42 } 43 return true 44 } 45 46 // If f() doesn't succeed within the timeout, return the last 47 // encountered error. 48 if err := Predicate(pred, timeout); err != nil { 49 return predErr 50 } 51 52 return nil 53 } 54 55 // Invariant is a helper test function that will wait for a timeout period of 56 // time, verifying that a statement remains true for the entire duration. This 57 // function is helpful as timing doesn't always line up well when running 58 // integration tests with several running lnd nodes. This function gives callers 59 // a way to assert that some property is maintained over a particular time 60 // frame. 61 func Invariant(statement func() bool, timeout time.Duration) error { 62 const pollInterval = 20 * time.Millisecond 63 64 exitTimer := time.After(timeout) 65 for { 66 <-time.After(pollInterval) 67 68 // Fail if the invariant is broken while polling. 69 if !statement() { 70 return fmt.Errorf("invariant broken before time out") 71 } 72 73 select { 74 case <-exitTimer: 75 return nil 76 default: 77 } 78 } 79 } 80 81 // InvariantNoError is a wrapper around Invariant that waits out the duration 82 // specified by timeout. It fails if the predicate ever returns an error during 83 // that time. 84 func InvariantNoError(f func() error, timeout time.Duration) error { 85 var predErr error 86 pred := func() bool { 87 if err := f(); err != nil { 88 predErr = err 89 return false 90 } 91 return true 92 } 93 94 if err := Invariant(pred, timeout); err != nil { 95 return predErr 96 } 97 98 return nil 99 }