Skip to content

Commit

Permalink
Make tests limiter implementation agnostic 1/2
Browse files Browse the repository at this point in the history
The ovarall goal is to be able to run the same tests on all possible
implementations so that we can verify they're working.

After #42 we can now configure limiters with the same options.

After this diff, the tests only pass in those options in to the testRunner.

A following diff will modify testRunner so that all tests are executed
on both atomic & mutex based limiters.

This in turn allows us to change the limiters in sync & unblocks
resolving #27 & #23 (they are about the same bug)

This diff also
- changes the test to run in the same package.
  This is just so that I can access `option` without making it public,
  which seems unnecessary.
- renames runner into testRunner since it appears the benchmarks
  already define a `runner`. We might be able to merge them
  together but that's for another diff.
  • Loading branch information
rabbbit committed Dec 7, 2020
1 parent 3f3255d commit 1617caa
Showing 1 changed file with 11 additions and 10 deletions.
21 changes: 11 additions & 10 deletions ratelimit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ import (
)

type runner interface {
// createLimiter builds a limiter with given options.
createLimiter(int, ...ratelimit.Option) ratelimit.Limiter
// startTaking tries to Take() on passed in limiters in a loop/goroutine.
startTaking(rls ...ratelimit.Limiter)
// assertCountAt asserts the limiters have Taken() a number of times at the given time.
// It's a thin wrapper around afterFunc to reduce boilerplate code.
assertCountAt(d time.Duration, count int)
// getClock returns the test clock.
getClock() ratelimit.Clock
// afterFunc executes a func at a given time.
// not using clock.AfterFunc because andres-erbsen/clock misses a nap there.
afterFunc(d time.Duration, fn func())
Expand Down Expand Up @@ -51,6 +51,12 @@ func runTest(t *testing.T, fn func(runner)) {
r.clock.Add(r.maxDuration)
}

// createLimiter builds a limiter with given options.
func (r *runnerImpl) createLimiter(rate int, opts ...ratelimit.Option) ratelimit.Limiter {
opts = append(opts, ratelimit.WithClock(r.clock))
return ratelimit.New(rate, opts...)
}

// startTaking tries to Take() on passed in limiters in a loop/goroutine.
func (r *runnerImpl) startTaking(rls ...ratelimit.Limiter) {
r.goWait(func() {
Expand All @@ -77,11 +83,6 @@ func (r *runnerImpl) assertCountAt(d time.Duration, count int) {
})
}

// getClock return the test clock.
func (r *runnerImpl) getClock() ratelimit.Clock {
return r.clock
}

// afterFunc executes a func at a given time.
func (r *runnerImpl) afterFunc(d time.Duration, fn func()) {
if d > r.maxDuration {
Expand Down Expand Up @@ -144,7 +145,7 @@ func TestUnlimited(t *testing.T) {

func TestRateLimiter(t *testing.T) {
runTest(t, func(r runner) {
rl := ratelimit.New(100, ratelimit.WithClock(r.getClock()), ratelimit.WithoutSlack)
rl := r.createLimiter(100, ratelimit.WithoutSlack)

// Create copious counts concurrently.
r.startTaking(rl)
Expand All @@ -160,8 +161,8 @@ func TestRateLimiter(t *testing.T) {

func TestDelayedRateLimiter(t *testing.T) {
runTest(t, func(r runner) {
slow := ratelimit.New(10, ratelimit.WithClock(r.getClock()))
fast := ratelimit.New(100, ratelimit.WithClock(r.getClock()))
slow := r.createLimiter(10, ratelimit.WithoutSlack)
fast := r.createLimiter(100, ratelimit.WithoutSlack)

// Run a slow startTaking
r.startTaking(slow, fast)
Expand Down

0 comments on commit 1617caa

Please sign in to comment.