Skip to content

Commit ad2265b

Browse files
author
Seth Ammons
authored
Merge pull request #20 from meson10/master
Test Improvements & LogHook Support.
2 parents 2c5fb96 + 9c8497d commit ad2265b

File tree

2 files changed

+125
-19
lines changed

2 files changed

+125
-19
lines changed

main.go

+17-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ type Client struct {
3333
MaxRetries int
3434
Backoff BackoffStrategy
3535
KeepLog bool
36+
LogHook LogHook
3637

3738
SuccessReqNum int
3839
SuccessRetryNum int
@@ -95,6 +96,10 @@ func NewExtendedClient(hc *http.Client) *Client {
9596
return c
9697
}
9798

99+
// PrintErrStrategy is used to log attempts as they happen.
100+
// You know, more visible
101+
type LogHook func(e ErrEntry)
102+
98103
// BackoffStrategy is used to determine how long a retry request should wait until attempted
99104
type BackoffStrategy func(retry int) time.Duration
100105

@@ -336,12 +341,17 @@ func (c *Client) LogString() string {
336341
defer c.Unlock()
337342
var res string
338343
for _, e := range c.ErrLog {
339-
res += fmt.Sprintf("%d %s [%s] %s request-%d retry-%d error: %s\n",
340-
e.Time.Unix(), e.Method, e.Verb, e.URL, e.Request, e.Retry, e.Err)
344+
res += c.FormatError(e)
341345
}
342346
return res
343347
}
344348

349+
// Format the Error to human readable string
350+
func (c *Client) FormatError(e ErrEntry) string {
351+
return fmt.Sprintf("%d %s [%s] %s request-%d retry-%d error: %s\n",
352+
e.Time.Unix(), e.Method, e.Verb, e.URL, e.Request, e.Retry, e.Err)
353+
}
354+
345355
// LogErrCount is a helper method used primarily for test validation
346356
func (c *Client) LogErrCount() int {
347357
c.Lock()
@@ -358,8 +368,12 @@ func (c *Client) EmbedHTTPClient(hc *http.Client) {
358368
func (c *Client) log(e ErrEntry) {
359369
if c.KeepLog {
360370
c.Lock()
371+
defer c.Unlock()
361372
c.ErrLog = append(c.ErrLog, e)
362-
c.Unlock()
373+
} else if c.LogHook != nil {
374+
// NOTE: There is a possibility that Log Printing hook slows it down.
375+
// but the consumer can always do the Job in a go-routine.
376+
c.LogHook(e)
363377
}
364378
}
365379

main_test.go

+108-16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package pester_test
1+
package pester
22

33
import (
44
"fmt"
@@ -13,14 +13,13 @@ import (
1313

1414
"net/http"
1515
"net/http/cookiejar"
16-
17-
"github.com/sethgrid/pester"
16+
"errors"
1817
)
1918

2019
func TestConcurrentRequests(t *testing.T) {
2120
t.Parallel()
2221

23-
c := pester.New()
22+
c := New()
2423
c.Concurrency = 3
2524
c.KeepLog = true
2625

@@ -43,7 +42,7 @@ func TestConcurrentRequests(t *testing.T) {
4342
func TestConcurrent2Retry0(t *testing.T) {
4443
t.Parallel()
4544

46-
c := pester.New()
45+
c := New()
4746
c.Concurrency = 2
4847
c.MaxRetries = 0
4948
c.KeepLog = true
@@ -67,7 +66,7 @@ func TestConcurrent2Retry0(t *testing.T) {
6766
func TestDefaultBackoff(t *testing.T) {
6867
t.Parallel()
6968

70-
c := pester.New()
69+
c := New()
7170
c.KeepLog = true
7271

7372
nonExistantURL := "http://localhost:9000/foo"
@@ -102,10 +101,90 @@ func TestDefaultBackoff(t *testing.T) {
102101

103102
}
104103

104+
func TestFormatError(t *testing.T) {
105+
t.Parallel()
106+
err := errors.New("Get http://localhost:9000/foo: dial tcp 127.0.0.1:9000: getsockopt: connection refused")
107+
expected := "1491271979 Get [GET] http://localhost:9000/foo request-0 retry-2 error: "+ err.Error()+"\n"
108+
109+
e := ErrEntry{
110+
Time: time.Unix(1491271979, 0),
111+
Method: "Get",
112+
URL: "http://localhost:9000/foo",
113+
Verb: http.MethodGet,
114+
Request: 0,
115+
Retry: 2,
116+
Attempt: 1,
117+
Err: err,
118+
}
119+
120+
c := New()
121+
formatted := c.FormatError(e)
122+
if strings.Compare(expected, formatted) != 0 {
123+
t.Errorf("\nExpected:\n%s\nGot:\n%s", expected, formatted)
124+
}
125+
}
126+
127+
func TestCustomLogHook(t *testing.T) {
128+
t.Parallel()
129+
130+
expectedRetries := 5
131+
errorLines := []ErrEntry{}
132+
133+
c := New()
134+
//c.KeepLog = true
135+
c.MaxRetries = expectedRetries
136+
c.Backoff = func(_ int) time.Duration {
137+
return 10 * time.Microsecond
138+
}
139+
140+
c.LogHook = func(e ErrEntry) {
141+
errorLines = append(errorLines, e)
142+
}
143+
144+
nonExistantURL := "http://localhost:9000/foo"
145+
146+
_, err := c.Get(nonExistantURL)
147+
if err == nil {
148+
t.Fatal("expected to get an error")
149+
}
150+
c.Wait()
151+
152+
// in the event of an error, let's see what the logs were
153+
if expectedRetries != len(errorLines) {
154+
t.Errorf("Expected %d lines to be emitted. Got %d", expectedRetries, errorLines)
155+
}
156+
}
157+
158+
func TestDefaultLogHook(t *testing.T) {
159+
t.Parallel()
160+
161+
errorLines := 0
162+
163+
c := New()
164+
//c.KeepLog = true
165+
c.MaxRetries = 5
166+
c.Backoff = func(_ int) time.Duration {
167+
return 10 * time.Microsecond
168+
}
169+
170+
nonExistantURL := "http://localhost:9000/foo"
171+
172+
_, err := c.Get(nonExistantURL)
173+
if err == nil {
174+
t.Fatal("expected to get an error")
175+
}
176+
c.Wait()
177+
178+
// in the event of an error, let's see what the logs were
179+
if errorLines != 0 {
180+
t.Errorf("Expected 0 lines to be emitted. Got %d", errorLines)
181+
}
182+
}
183+
105184
func TestLinearJitterBackoff(t *testing.T) {
106185
t.Parallel()
107-
c := pester.New()
108-
c.Backoff = pester.LinearJitterBackoff
186+
c := New()
187+
c.Backoff = LinearJitterBackoff
109188
c.KeepLog = true
110189

111190
nonExistantURL := "http://localhost:9000/foo"
@@ -142,9 +221,9 @@ func TestLinearJitterBackoff(t *testing.T) {
142221
func TestExponentialBackoff(t *testing.T) {
143222
t.Parallel()
144223

145-
c := pester.New()
224+
c := New()
146225
c.MaxRetries = 4
147-
c.Backoff = pester.ExponentialBackoff
226+
c.Backoff = ExponentialBackoff
148227
c.KeepLog = true
149228

150229
nonExistantURL := "http://localhost:9000/foo"
@@ -193,7 +272,7 @@ func TestCookiesJarPersistence(t *testing.T) {
193272
t.Fatal("Cannot create cookiejar", err)
194273
}
195274

196-
c := pester.New()
275+
c := New()
197276
c.Jar = jar
198277

199278
url := fmt.Sprintf("http://localhost:%d", port)
@@ -221,7 +300,7 @@ func TestEmbeddedClientTimeout(t *testing.T) {
221300
hc := http.DefaultClient
222301
hc.Timeout = clientTimeout
223302

224-
c := pester.NewExtendedClient(hc)
303+
c := NewExtendedClient(hc)
225304
_, err = c.Get(fmt.Sprintf("http://localhost:%d/", port))
226305
if err == nil {
227306
t.Error("expected a timeout error, did not get it")
@@ -230,7 +309,7 @@ func TestEmbeddedClientTimeout(t *testing.T) {
230309

231310
func TestConcurrentRequestsNotRacyAndDontLeak_FailedRequest(t *testing.T) {
232311
goroStart := runtime.NumGoroutine()
233-
c := pester.New()
312+
c := New()
234313
port, err := cookieServer()
235314
if err != nil {
236315
t.Fatalf("unable to start server %v", err)
@@ -277,7 +356,7 @@ func TestConcurrentRequestsNotRacyAndDontLeak_FailedRequest(t *testing.T) {
277356

278357
func TestConcurrentRequestsNotRacyAndDontLeak_SuccessfulRequest(t *testing.T) {
279358
goroStart := runtime.NumGoroutine()
280-
c := pester.New()
359+
c := New()
281360
nonExistantURL := "http://localhost:9000/foo"
282361
conc := 5
283362
errCh := make(chan error, conc)
@@ -343,7 +422,13 @@ func cookieServer() (int, error) {
343422
log.Fatalf("slow-server error %v", err)
344423
}
345424
}()
346-
port, err := strconv.Atoi(strings.Replace(l.Addr().String(), "[::]:", "", 1))
425+
426+
var port int
427+
_, sport, err := net.SplitHostPort(l.Addr().String())
428+
if err == nil {
429+
port, err = strconv.Atoi(sport)
430+
}
431+
347432
if err != nil {
348433
return -1, fmt.Errorf("unable to determine port %v", err)
349434
}
@@ -365,9 +450,16 @@ func timeoutServer(timeout time.Duration) (int, error) {
365450
log.Fatalf("slow-server error %v", err)
366451
}
367452
}()
368-
port, err := strconv.Atoi(strings.Replace(l.Addr().String(), "[::]:", "", 1))
453+
454+
var port int
455+
_, sport, err := net.SplitHostPort(l.Addr().String())
456+
if err == nil {
457+
port, err = strconv.Atoi(sport)
458+
}
459+
369460
if err != nil {
370461
return -1, fmt.Errorf("unable to determine port %v", err)
371462
}
463+
372464
return port, nil
373465
}

0 commit comments

Comments
 (0)