-
Notifications
You must be signed in to change notification settings - Fork 2.1k
/
wait.go
98 lines (83 loc) · 2.46 KB
/
wait.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
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
}