...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package testutil
16
17 import (
18 "bytes"
19 "fmt"
20 "path/filepath"
21 "runtime"
22 "strconv"
23 "testing"
24 "time"
25 )
26
27
28
29
30 func Retry(t *testing.T, maxAttempts int, sleep time.Duration, f func(r *R)) bool {
31 for attempt := 1; attempt <= maxAttempts; attempt++ {
32 r := &R{Attempt: attempt, log: &bytes.Buffer{}}
33
34 f(r)
35
36 if !r.failed {
37 if r.log.Len() != 0 {
38 t.Logf("Success after %d attempts:%s", attempt, r.log.String())
39 }
40 return true
41 }
42
43 if attempt == maxAttempts {
44 t.Logf("FAILED after %d attempts:%s", attempt, r.log.String())
45 t.Fail()
46 }
47
48 time.Sleep(sleep)
49 }
50 return false
51 }
52
53
54
55 func RetryWithoutTest(maxAttempts int, sleep time.Duration, f func(r *R)) bool {
56 for attempt := 1; attempt <= maxAttempts; attempt++ {
57 r := &R{Attempt: attempt, log: &bytes.Buffer{}}
58
59 f(r)
60
61 if !r.failed {
62 if r.log.Len() != 0 {
63 r.Logf("Success after %d attempts:%s", attempt, r.log.String())
64 }
65 return true
66 }
67
68 if attempt == maxAttempts {
69 r.Logf("FAILED after %d attempts:%s", attempt, r.log.String())
70 return false
71 }
72
73 time.Sleep(sleep)
74 }
75 return false
76 }
77
78
79 type R struct {
80
81 Attempt int
82
83 failed bool
84 log *bytes.Buffer
85 }
86
87
88 func (r *R) Fail() {
89 r.failed = true
90 }
91
92
93 func (r *R) Errorf(s string, v ...interface{}) {
94 r.logf(s, v...)
95 r.Fail()
96 }
97
98
99
100 func (r *R) Logf(s string, v ...interface{}) {
101 r.logf(s, v...)
102 }
103
104 func (r *R) logf(s string, v ...interface{}) {
105 fmt.Fprint(r.log, "\n")
106 fmt.Fprint(r.log, lineNumber())
107 fmt.Fprintf(r.log, s, v...)
108 }
109
110 func lineNumber() string {
111 _, file, line, ok := runtime.Caller(3)
112 if !ok {
113 return ""
114 }
115 return filepath.Base(file) + ":" + strconv.Itoa(line) + ": "
116 }
117
View as plain text