From f0f7677a51f1a5d6daa011c5f6a92a381cb4188e Mon Sep 17 00:00:00 2001 From: FishGoddess Date: Wed, 7 Jan 2026 21:11:40 +0800 Subject: [PATCH 1/2] =?UTF-8?q?100%=E8=A6=86=E7=9B=96=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HISTORY.md | 6 ++++ _icons/coverage.svg | 4 +-- executor.go | 16 +++++---- executor_test.go | 87 +++++++++++++++++++++++++++++++++++++++++++++ limiter_test.go | 17 +++++++++ 5 files changed, 121 insertions(+), 9 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 04ecc75..396660d 100755 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,11 @@ ## ✒ 历史版本的特性介绍 (Features in old versions) +### v0.3.2 + +> 此版本发布于 2026-01-07 + +* 完善单元测试,将覆盖率提升到 100% + ### v0.3.1-alpha > 此版本发布于 2026-01-07 diff --git a/_icons/coverage.svg b/_icons/coverage.svg index 7f6c81e..303f691 100644 --- a/_icons/coverage.svg +++ b/_icons/coverage.svg @@ -10,7 +10,7 @@ coverage coverage - 86% - 86% + 100% + 100% \ No newline at end of file diff --git a/executor.go b/executor.go index 3c02362..42c2282 100644 --- a/executor.go +++ b/executor.go @@ -24,10 +24,11 @@ var ( type Executor struct { conf *config - tasks chan Task - done chan struct{} - closed atomic.Bool - group sync.WaitGroup + workers uint + tasks chan Task + done chan struct{} + closed atomic.Bool + group sync.WaitGroup } // NewExecutor creates a executor with workers. @@ -43,9 +44,10 @@ func NewExecutor(workers uint, opts ...Option) *Executor { } executor := &Executor{ - conf: conf, - tasks: make(chan Task, conf.queueSize), - done: make(chan struct{}), + conf: conf, + workers: workers, + tasks: make(chan Task, conf.queueSize), + done: make(chan struct{}), } for range workers { diff --git a/executor_test.go b/executor_test.go index 74dce2e..2554043 100644 --- a/executor_test.go +++ b/executor_test.go @@ -49,3 +49,90 @@ func TestExecutor(t *testing.T) { t.Fatalf("gotTotalCount %d != totalCount %d", gotTotalCount, totalCount) } } + +// go test -v -cover -run=^TestExecutorMinMax$ +func TestExecutorMinMax(t *testing.T) { + executor := NewExecutor(minWorkers - 1) + + if executor.workers != minWorkers { + t.Fatalf("got %d != want %d", executor.workers, minWorkers) + } + + executor.Close() + executor = NewExecutor(maxWorkers + 1) + + if executor.workers != maxWorkers { + t.Fatalf("got %d != want %d", executor.workers, maxWorkers) + } + + executor.Close() +} + +// go test -v -cover -run=^TestExecutorContext$ +func TestExecutorContext(t *testing.T) { + executor := NewExecutor(4, WithQueueSize(1)) + defer executor.Close() + + got := uint(cap(executor.tasks)) + if got != executor.conf.queueSize { + t.Fatalf("got %d != want %d", got, executor.conf.queueSize) + } + + ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) + defer cancel() + + for i := uint(0); i <= executor.workers; i++ { + err := executor.Submit(ctx, func() { + time.Sleep(200 * time.Millisecond) + }) + + if err != nil { + t.Fatal(err) + } + } + + err := executor.Submit(ctx, func() {}) + if err != context.DeadlineExceeded { + t.Fatalf("got %+v != want %+v", err, context.DeadlineExceeded) + } +} + +// go test -v -cover -run=^TestExecutorClose$ +func TestExecutorClose(t *testing.T) { + executor := NewExecutor(4, WithQueueSize(1)) + defer executor.Close() + + if executor.closed.Load() { + t.Fatal("executor is closed") + } + + ctx := context.Background() + for i := uint(0); i <= executor.workers; i++ { + err := executor.Submit(ctx, func() { + time.Sleep(200 * time.Millisecond) + }) + + if err != nil { + t.Fatal(err) + } + } + + go func() { + err := executor.Submit(ctx, func() {}) + if err != ErrExecutorClosed { + t.Errorf("got %+v != want %+v", err, ErrExecutorClosed) + } + }() + + time.Sleep(10 * time.Millisecond) + executor.Close() + + if !executor.closed.Load() { + t.Fatal("executor not closed") + } + + err := executor.Submit(ctx, func() {}) + if err != ErrExecutorClosed { + t.Errorf("got %+v != want %+v", err, ErrExecutorClosed) + } +} diff --git a/limiter_test.go b/limiter_test.go index 386be7e..28a8b95 100644 --- a/limiter_test.go +++ b/limiter_test.go @@ -46,3 +46,20 @@ func TestLimiter(t *testing.T) { t.Fatalf("gotTotalCount %d != totalCount %d", gotTotalCount, totalCount) } } + +// go test -v -cover -run=^TestLimiterMinMax$ +func TestLimiterMinMax(t *testing.T) { + limiter := NewLimiter(minLimit - 1) + + got := cap(limiter.tokens) + if got != minLimit { + t.Fatalf("got %d != want %d", got, minLimit) + } + + limiter = NewLimiter(maxLimit + 1) + + got = cap(limiter.tokens) + if got != maxLimit { + t.Fatalf("got %d != want %d", got, maxLimit) + } +} From 9cd577709c0a11427d495a55f8233390335086d9 Mon Sep 17 00:00:00 2001 From: FishGoddess Date: Wed, 7 Jan 2026 21:13:56 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.en.md | 4 ++-- README.md | 4 ++-- _examples/basic.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.en.md b/README.en.md index 2e72ebf..b81cfa5 100755 --- a/README.en.md +++ b/README.en.md @@ -36,7 +36,7 @@ import ( func main() { ctx := context.Background() - // Limits the number of simultaneous goroutines and not reuses them. + // Limits goroutines. limiter := goes.NewLimiter(4) for i := 0; i < 20; i++ { @@ -48,7 +48,7 @@ func main() { limiter.Wait() - // Limits the number of simultaneous goroutines and reuses them. + // Reuses goroutines. executor := goes.NewExecutor(4) defer executor.Close() diff --git a/README.md b/README.md index f0cfc29..6127a78 100755 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ import ( func main() { ctx := context.Background() - // Limits the number of simultaneous goroutines and not reuses them. + // Limits goroutines. limiter := goes.NewLimiter(4) for i := 0; i < 20; i++ { @@ -48,7 +48,7 @@ func main() { limiter.Wait() - // Limits the number of simultaneous goroutines and reuses them. + // Reuses goroutines. executor := goes.NewExecutor(4) defer executor.Close() diff --git a/_examples/basic.go b/_examples/basic.go index 58666b0..24d4a3c 100644 --- a/_examples/basic.go +++ b/_examples/basic.go @@ -15,7 +15,7 @@ import ( func main() { ctx := context.Background() - // Limits the number of simultaneous goroutines and not reuses them. + // Limits goroutines. limiter := goes.NewLimiter(4) for i := 0; i < 20; i++ { @@ -27,7 +27,7 @@ func main() { limiter.Wait() - // Limits the number of simultaneous goroutines and reuses them. + // Reuses goroutines. executor := goes.NewExecutor(4) defer executor.Close()