From e9935551b1c81dc209ab1e54b5d3eaa3d2c9f6b3 Mon Sep 17 00:00:00 2001 From: Kostiantyn Masliuk Date: Tue, 1 Sep 2020 00:58:41 +0200 Subject: [PATCH] add runners tests --- atomic.go | 4 --- executors.go => runnables.go | 6 ++++ runners.go | 17 ++++----- runners_test.go | 68 ++++++++++++++++++++++++++++++++++++ throttlers.go | 16 +++++++++ throttlers_test.go | 2 +- 6 files changed, 100 insertions(+), 13 deletions(-) rename executors.go => runnables.go (94%) create mode 100644 runners_test.go diff --git a/atomic.go b/atomic.go index 878425d..627ca4f 100644 --- a/atomic.go +++ b/atomic.go @@ -41,10 +41,6 @@ func atomicIncr(number *uint64) uint64 { return atomic.AddUint64(number, 1) } -func atomicDecr(number *uint64) uint64 { - return atomic.AddUint64(number, ^uint64(0)) -} - func atomicSet(number *uint64, value uint64) uint64 { atomic.StoreUint64(number, value) return value diff --git a/executors.go b/runnables.go similarity index 94% rename from executors.go rename to runnables.go index a9fe48c..e5ba110 100644 --- a/executors.go +++ b/runnables.go @@ -9,6 +9,12 @@ import ( type Runnable func(context.Context) error +func use(err error) Runnable { + return func(ctx context.Context) error { + return err + } +} + func nope(context.Context) error { return nil } diff --git a/runners.go b/runners.go index 94eddde..e95def9 100644 --- a/runners.go +++ b/runners.go @@ -22,7 +22,7 @@ func NewRunnerSync(ctx context.Context, thr Throttler) *rsync { ctx, cancel := context.WithCancel(ctx) r := rsync{thr: thr, ctx: ctx} r.report = func(err error) { - if r.err != nil { + if r.err == nil && err != nil { r.err = err cancel() } @@ -47,7 +47,7 @@ func (r *rsync) Run(run Runnable) { default: } if err := run(r.ctx); err != nil { - r.report(fmt.Errorf("function error has happened %w", err)) + r.report(fmt.Errorf("runnable error has happened %w", err)) return } } @@ -69,10 +69,12 @@ func NewRunnerAsync(ctx context.Context, thr Throttler) *rasync { r := rasync{thr: thr, ctx: ctx} var once sync.Once r.report = func(err error) { - once.Do(func() { - r.err = err - cancel() - }) + if err != nil { + once.Do(func() { + r.err = err + cancel() + }) + } } return &r } @@ -97,7 +99,7 @@ func (r *rasync) Run(run Runnable) { default: } if err := run(r.ctx); err != nil { - r.report(fmt.Errorf("function error has happened %w", err)) + r.report(fmt.Errorf("runnable error has happened %w", err)) return } }() @@ -105,6 +107,5 @@ func (r *rasync) Run(run Runnable) { func (r *rasync) Result() error { r.wg.Wait() - r.report(nil) return r.err } diff --git a/runners_test.go b/runners_test.go new file mode 100644 index 0000000..072991e --- /dev/null +++ b/runners_test.go @@ -0,0 +1,68 @@ +package gohalt + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRunners(t *testing.T) { + cctx, cancel := context.WithCancel(context.Background()) + cancel() + table := map[string]struct { + r Runner + run Runnable + err error + }{ + "Runner sync should return error on throttling": { + r: NewRunnerSync(context.Background(), tmock{aerr: errors.New("test")}), + run: nope, + err: fmt.Errorf("throttler error has happened %w", errors.New("test")), + }, + "Runner sync should return error on realising error": { + r: NewRunnerSync(context.Background(), tmock{rerr: errors.New("test")}), + run: nope, + err: fmt.Errorf("throttler error has happened %w", errors.New("test")), + }, + "Runner sync should return error on runnable error": { + r: NewRunnerSync(context.Background(), tmock{}), + run: use(errors.New("test")), + err: fmt.Errorf("runnable error has happened %w", errors.New("test")), + }, + "Runner sync should return error on canceled context": { + r: NewRunnerSync(cctx, tmock{}), + run: nope, + err: fmt.Errorf("context error has happened %w", cctx.Err()), + }, + "Runner async should return error on throttling": { + r: NewRunnerAsync(context.Background(), tmock{aerr: errors.New("test")}), + run: nope, + err: fmt.Errorf("throttler error has happened %w", errors.New("test")), + }, + "Runner async should return error on realising error": { + r: NewRunnerAsync(context.Background(), tmock{rerr: errors.New("test")}), + run: nope, + err: fmt.Errorf("throttler error has happened %w", errors.New("test")), + }, + "Runner async should return error on runnable error": { + r: NewRunnerAsync(context.Background(), tmock{}), + run: use(errors.New("test")), + err: fmt.Errorf("runnable error has happened %w", errors.New("test")), + }, + "Runner async should return error on canceled context": { + r: NewRunnerAsync(cctx, tmock{}), + run: nope, + err: fmt.Errorf("context error has happened %w", cctx.Err()), + }, + } + for tname, tcase := range table { + t.Run(tname, func(t *testing.T) { + tcase.r.Run(tcase.run) + err := tcase.r.Result() + assert.Equal(t, tcase.err, err) + }) + } +} diff --git a/throttlers.go b/throttlers.go index 523df62..d8852b6 100644 --- a/throttlers.go +++ b/throttlers.go @@ -46,6 +46,22 @@ type tvisitor interface { tvisitSuppress(context.Context, *tsuppress) } +type tmock struct { + aerr error + rerr error +} + +func (tmock) accept(context.Context, tvisitor) { +} + +func (thr tmock) Acquire(context.Context) error { + return thr.aerr +} + +func (thr tmock) Release(context.Context) error { + return thr.rerr +} + type techo struct { err error } diff --git a/throttlers_test.go b/throttlers_test.go index 0ba5f26..e684bbf 100644 --- a/throttlers_test.go +++ b/throttlers_test.go @@ -98,7 +98,7 @@ func (t *tcase) result(index int) (err error, dur time.Duration) { return } -func TestThrottlerPattern(t *testing.T) { +func TestThrottlers(t *testing.T) { cctx, cancel := context.WithCancel(context.Background()) cancel() table := map[string]tcase{