Skip to content

Commit

Permalink
use quicktest for testing
Browse files Browse the repository at this point in the history
This slims down the dependencies considerably, which is appropriate
for a low level package like retry.

For the time being, we also use a fork of the juju/clock package that
also uses quicktest until juju/clock#5
lands.
  • Loading branch information
rogpeppe committed May 15, 2019
1 parent 2602fa8 commit 974d627
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 100 deletions.
17 changes: 4 additions & 13 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
module gopkg.in/retry.v1

require (
github.com/juju/clock v0.0.0-20180808021310-bab88fc67299
github.com/juju/errors v0.0.0-20180726005433-812b06ada177 // indirect
github.com/juju/loggo v0.0.0-20180524022052-584905176618 // indirect
github.com/juju/retry v0.0.0-20160928201858-1998d01ba1c3 // indirect
github.com/juju/testing v0.0.0-20180517134105-72703b1e95eb
github.com/juju/utils v0.0.0-20180619112806-c746c6e86f4f
github.com/juju/version v0.0.0-20180108022336-b64dbd566305 // indirect
github.com/kr/pretty v0.1.0 // indirect
golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb // indirect
golang.org/x/net v0.0.0-20180724234803-3673e40ba225 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce // indirect
gopkg.in/yaml.v2 v2.2.1 // indirect
github.com/frankban/quicktest v1.2.2
github.com/rogpeppe/clock v0.0.0-20190514195947-2896927a307a
)

go 1.12
30 changes: 6 additions & 24 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,29 +1,11 @@
github.com/juju/clock v0.0.0-20180808021310-bab88fc67299 h1:K9nBHQ3UNqg/HhZkQnGG2AE4YxDyNmGS9FFT2gGegLQ=
github.com/juju/clock v0.0.0-20180808021310-bab88fc67299/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA=
github.com/juju/errors v0.0.0-20180726005433-812b06ada177 h1:UliPGoJWlIH3IkkFqnPy/xYF/2tkTRTZhMt8/CwGUvw=
github.com/juju/errors v0.0.0-20180726005433-812b06ada177/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
github.com/juju/loggo v0.0.0-20180524022052-584905176618 h1:MK144iBQF9hTSwBW/9eJm034bVoG30IshVm688T2hi8=
github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
github.com/juju/retry v0.0.0-20160928201858-1998d01ba1c3 h1:56R9RckAEUeaptI0yGE8tzNAs3dD6Wf7giI6D51Czx8=
github.com/juju/retry v0.0.0-20160928201858-1998d01ba1c3/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4=
github.com/juju/testing v0.0.0-20180517134105-72703b1e95eb h1:oHBF98WnC1lqCv/W7I7gxnLjD6xJieJ8yt/3IrnMthY=
github.com/juju/testing v0.0.0-20180517134105-72703b1e95eb/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
github.com/juju/utils v0.0.0-20180619112806-c746c6e86f4f h1:ig+5pmJmjxPAf8bwQUDpo7Z0E5l6nh1xE8artIt+A/Y=
github.com/juju/utils v0.0.0-20180619112806-c746c6e86f4f/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk=
github.com/juju/version v0.0.0-20180108022336-b64dbd566305 h1:lQxPJ1URr2fjsKnJRt/BxiIxjLt9IKGvS+0injMHbag=
github.com/juju/version v0.0.0-20180108022336-b64dbd566305/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U=
github.com/frankban/quicktest v1.2.2 h1:xfmOhhoH5fGPgbEAlhLpJH9p0z/0Qizio9osmvn9IUY=
github.com/frankban/quicktest v1.2.2/go.mod h1:Qh/WofXFeiAFII1aEBu529AtJo6Zg2VHscnEsbBnJ20=
github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42 h1:q3pnF5JFBNRz8sRD+IRj7Y6DMyYGTNqnZ9axTbSfoNI=
github.com/google/go-cmp v0.2.1-0.20190312032427-6f77996f0c42/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb h1:Ah9YqXLj6fEgeKqcmBuLCbAsrF3ScD7dJ/bYM0C6tXI=
golang.org/x/crypto v0.0.0-20180723164146-c126467f60eb/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225 h1:kNX+jCowfMYzvlSvJu5pQWEmyWFrBXJ3PBy10xKMXK8=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
github.com/rogpeppe/clock v0.0.0-20190514195947-2896927a307a h1:3QH7VyOaaiUHNrA9Se4YQIRkDTCw1EJls9xTUCaCeRM=
github.com/rogpeppe/clock v0.0.0-20190514195947-2896927a307a/go.mod h1:4r5QyqhjIWCcK8DO4KMclc5Iknq5qVBAlbYYzAbUScQ=
14 changes: 0 additions & 14 deletions package_test.go

This file was deleted.

104 changes: 55 additions & 49 deletions retry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@
package retry_test // import "gopkg.in/retry.v1"

import (
"testing"
"time"

"github.com/juju/clock/testclock"
gc "gopkg.in/check.v1"
"github.com/rogpeppe/clock/testclock"
qt "github.com/frankban/quicktest"

"gopkg.in/retry.v1"
)

type retrySuite struct{}

var _ = gc.Suite(&retrySuite{})

func (*retrySuite) TestAttemptTiming(c *gc.C) {
func TestAttemptTiming(t *testing.T) {
c := qt.New(t)
testAttempt := retry.Regular{
Total: 0.25e9,
Delay: 0.1e9,
Expand All @@ -29,8 +27,8 @@ func (*retrySuite) TestAttemptTiming(c *gc.C) {
got = append(got, time.Now().Sub(t0))
}
got = append(got, time.Now().Sub(t0))
c.Assert(a.Stopped(), gc.Equals, false)
c.Assert(got, gc.HasLen, len(want))
c.Assert(a.Stopped(), qt.Equals, false)
c.Assert(got, qt.HasLen, len(want))
const margin = 0.01e9
for i, got := range want {
lo := want[i] - margin
Expand All @@ -41,34 +39,36 @@ func (*retrySuite) TestAttemptTiming(c *gc.C) {
}
}

func (*retrySuite) TestAttemptNextMore(c *gc.C) {
func TestAttemptNextMore(t *testing.T) {
c := qt.New(t)
a := retry.Regular{}.Start(nil)
c.Assert(a.Next(), gc.Equals, true)
c.Assert(a.Next(), gc.Equals, false)
c.Assert(a.Next(), qt.Equals, true)
c.Assert(a.Next(), qt.Equals, false)

a = retry.Regular{}.Start(nil)
c.Assert(a.Next(), gc.Equals, true)
c.Assert(a.More(), gc.Equals, false)
c.Assert(a.Next(), gc.Equals, false)
c.Assert(a.Next(), qt.Equals, true)
c.Assert(a.More(), qt.Equals, false)
c.Assert(a.Next(), qt.Equals, false)

a = retry.Regular{Total: 2e8}.Start(nil)
c.Assert(a.Next(), gc.Equals, true)
c.Assert(a.More(), gc.Equals, true)
c.Assert(a.Next(), qt.Equals, true)
c.Assert(a.More(), qt.Equals, true)
time.Sleep(2e8)
c.Assert(a.More(), gc.Equals, true)
c.Assert(a.Next(), gc.Equals, true)
c.Assert(a.Next(), gc.Equals, false)
c.Assert(a.More(), qt.Equals, true)
c.Assert(a.Next(), qt.Equals, true)
c.Assert(a.Next(), qt.Equals, false)

a = retry.Regular{Total: 1e8, Min: 2}.Start(nil)
time.Sleep(1e8)
c.Assert(a.Next(), gc.Equals, true)
c.Assert(a.More(), gc.Equals, true)
c.Assert(a.Next(), gc.Equals, true)
c.Assert(a.More(), gc.Equals, false)
c.Assert(a.Next(), gc.Equals, false)
c.Assert(a.Next(), qt.Equals, true)
c.Assert(a.More(), qt.Equals, true)
c.Assert(a.Next(), qt.Equals, true)
c.Assert(a.More(), qt.Equals, false)
c.Assert(a.Next(), qt.Equals, false)
}

func (*retrySuite) TestAttemptWithStop(c *gc.C) {
func TestAttemptWithStop(t *testing.T) {
c := qt.New(t)
stop := make(chan struct{})
close(stop)
done := make(chan struct{})
Expand All @@ -81,13 +81,14 @@ func (*retrySuite) TestAttemptWithStop(c *gc.C) {
for a.Next() {
c.Errorf("unexpected attempt")
}
c.Check(a.Stopped(), gc.Equals, true)
c.Check(a.Stopped(), qt.Equals, true)
close(done)
}()
assertReceive(c, done, "attempt loop abort")
}

func (*retrySuite) TestAttemptWithLaterStop(c *gc.C) {
func TestAttemptWithLaterStop(t *testing.T) {
c := qt.New(t)
clock := testclock.NewClock(time.Now())
stop := make(chan struct{})
done := make(chan struct{})
Expand All @@ -101,7 +102,7 @@ func (*retrySuite) TestAttemptWithLaterStop(c *gc.C) {
for a.Next() {
progress <- struct{}{}
}
c.Check(a.Stopped(), gc.Equals, true)
c.Check(a.Stopped(), qt.Equals, true)
close(done)
}()
assertReceive(c, progress, "progress")
Expand All @@ -117,7 +118,8 @@ func (*retrySuite) TestAttemptWithLaterStop(c *gc.C) {
}
}

func (*retrySuite) TestAttemptWithMockClock(c *gc.C) {
func TestAttemptWithMockClock(t *testing.T) {
c := qt.New(t)
clock := testclock.NewClock(time.Now())
strategy := retry.Regular{
Delay: 5 * time.Second,
Expand Down Expand Up @@ -251,14 +253,15 @@ var strategyTests = []strategyTest{{
terminates: true,
}}

func (*retrySuite) TestStrategies(c *gc.C) {
func TestStrategies(t *testing.T) {
c := qt.New(t)
for i, test := range strategyTests {
c.Logf("test %d: %s", i, test.about)
testStrategy(c, test)
}
}

func testStrategy(c *gc.C, test strategyTest) {
func testStrategy(c *qt.C, test strategyTest) {
t0 := time.Now()
clk := &mockClock{
now: t0,
Expand All @@ -269,17 +272,18 @@ func testStrategy(c *gc.C, test strategyTest) {
clk.now = t0.Add(call.t)
ok := a.Next()
expectTerminate := test.terminates && i == len(test.calls)-1
c.Assert(ok, gc.Equals, !expectTerminate)
c.Assert(ok, qt.Equals, !expectTerminate)
if got, want := clk.now.Sub(t0), call.t+call.sleep; !closeTo(got, want) {
c.Fatalf("incorrect time after Next; got %v want %v", got, want)
}
if ok {
c.Assert(a.Count(), gc.Equals, i+1)
c.Assert(a.Count(), qt.Equals, i+1)
}
}
}

func (*retrySuite) TestExponentialWithJitter(c *gc.C) {
func TestExponentialWithJitter(t *testing.T) {
c := qt.New(t)
// We use a stochastic test because we don't want
// to mock rand and have detailed dependence on
// the exact way it's used. We run the strategy many
Expand Down Expand Up @@ -345,7 +349,8 @@ func (*retrySuite) TestExponentialWithJitter(c *gc.C) {
}
}

func (*retrySuite) TestGapBetweenMoreAndNext(c *gc.C) {
func TestGapBetweenMoreAndNext(t *testing.T) {
c := qt.New(t)
t0 := time.Now().UTC()
clk := &mockClock{
now: t0,
Expand All @@ -354,27 +359,28 @@ func (*retrySuite) TestGapBetweenMoreAndNext(c *gc.C) {
Min: 3,
Delay: time.Second,
}).Start(clk)
c.Assert(a.Next(), gc.Equals, true)
c.Assert(clk.now, gc.Equals, t0)
c.Assert(a.Next(), qt.Equals, true)
c.Assert(clk.now, qt.Equals, t0)

clk.now = clk.now.Add(500 * time.Millisecond)
// Sanity check that the first iteration sleeps for half a second.
c.Assert(a.More(), gc.Equals, true)
c.Assert(a.Next(), gc.Equals, true)
c.Assert(clk.now.Sub(t0), gc.Equals, t0.Add(time.Second).Sub(t0))
c.Assert(a.More(), qt.Equals, true)
c.Assert(a.Next(), qt.Equals, true)
c.Assert(clk.now.Sub(t0), qt.Equals, t0.Add(time.Second).Sub(t0))

clk.now = clk.now.Add(500 * time.Millisecond)
c.Assert(a.More(), gc.Equals, true)
c.Assert(a.More(), qt.Equals, true)

// Add a delay between calling More and Next.
// Next should wait until the correct time anyway.
clk.now = clk.now.Add(250 * time.Millisecond)
c.Assert(a.More(), gc.Equals, true)
c.Assert(a.Next(), gc.Equals, true)
c.Assert(clk.now.Sub(t0), gc.Equals, t0.Add(2*time.Second).Sub(t0))
c.Assert(a.More(), qt.Equals, true)
c.Assert(a.Next(), qt.Equals, true)
c.Assert(clk.now.Sub(t0), qt.Equals, t0.Add(2*time.Second).Sub(t0))
}

func (*retrySuite) TestOnlyOneHitOnZeroTotal(c *gc.C) {
func TestOnlyOneHitOnZeroTotal(t *testing.T) {
c := qt.New(t)
t0 := time.Now().UTC()
clk := &mockClock{
now: t0,
Expand All @@ -385,8 +391,8 @@ func (*retrySuite) TestOnlyOneHitOnZeroTotal(c *gc.C) {
Min: 0,
}).Start(clk)
// Even if the clock didn't advanced we want to have only one hit
c.Check(a.Next(), gc.Equals, true)
c.Check(a.More(), gc.Equals, false)
c.Check(a.Next(), qt.Equals, true)
c.Check(a.More(), qt.Equals, false)
}

// closeTo reports whether d0 and d1 are close enough
Expand Down Expand Up @@ -418,7 +424,7 @@ func (c *mockClock) Now() time.Time {
return c.now
}

func assertReceive(c *gc.C, ch <-chan struct{}, what string) {
func assertReceive(c *qt.C, ch <-chan struct{}, what string) {
select {
case <-ch:
case <-time.After(time.Second):
Expand Down

0 comments on commit 974d627

Please sign in to comment.