-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from newmo-oss/add-gogrouptest
Add gogrouptest
- Loading branch information
Showing
7 changed files
with
215 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,12 @@ | ||
module github.com/newmo-oss/gogroup | ||
|
||
go 1.22.7 | ||
go 1.22.10 | ||
|
||
require ( | ||
github.com/google/go-cmp v0.6.0 | ||
github.com/google/uuid v1.6.0 | ||
github.com/newmo-oss/gotestingmock v0.1.1 | ||
github.com/newmo-oss/testid v0.1.0 | ||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 | ||
go.uber.org/goleak v1.3.0 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package gogrouptest | ||
|
||
import ( | ||
"context" | ||
"sync" | ||
"testing" | ||
|
||
"github.com/newmo-oss/testid" | ||
"github.com/sourcegraph/conc/panics" | ||
"github.com/sourcegraph/conc/pool" | ||
|
||
"github.com/newmo-oss/gogroup/internal" | ||
) | ||
|
||
var withoutParallels sync.Map | ||
|
||
func init() { | ||
if testing.Testing() { | ||
internal.Start = startForTest | ||
} | ||
} | ||
|
||
// WithoutParallel sets the parallel mode of [gogroup.Group] to off. | ||
// It makes (*gogroup.Group).Run will execute synchronously. | ||
// The parallel mode is set each test id which get from [testid.FromContext]. | ||
// If any test id cannot obtain from the context, the test will be fail with t.Fatal. | ||
// The mode will be remove by t.Cleanup. | ||
func WithoutParallel(t testing.TB, ctx context.Context) { | ||
tid, ok := testid.FromContext(ctx) | ||
if !ok { | ||
t.Fatal("failed to get test ID from the context") | ||
} | ||
|
||
t.Cleanup(func() { | ||
withoutParallels.Delete(tid) | ||
}) | ||
|
||
withoutParallels.Store(tid, true) | ||
} | ||
|
||
func noParallel(ctx context.Context) bool { | ||
tid, ok := testid.FromContext(ctx) | ||
if !ok { | ||
return false | ||
} | ||
|
||
v, ok := withoutParallels.Load(tid) | ||
if !ok { | ||
return false | ||
} | ||
|
||
noparallel, ok := v.(bool) | ||
if !ok { | ||
return false | ||
} | ||
|
||
return noparallel | ||
} | ||
|
||
func startForTest(ctx context.Context, funcs []func(context.Context) error) func() error { | ||
if !noParallel(ctx) { | ||
return internal.DefaultStart(ctx, funcs) | ||
} | ||
|
||
p := pool.New().WithContext(ctx).WithCancelOnError() | ||
doneCh := make([]chan struct{}, len(funcs)) | ||
|
||
for i, f := range funcs { | ||
doneCh[i] = make(chan struct{}) | ||
p.Go(func(ctx context.Context) (rerr error) { | ||
defer func() { | ||
close(doneCh[i]) | ||
}() | ||
|
||
// wait before function call | ||
if i > 0 { | ||
<-doneCh[i-1] | ||
} | ||
|
||
if r := panics.Try(func() { rerr = f(ctx) }); r != nil { | ||
return r.AsError() | ||
} | ||
|
||
return rerr | ||
}) | ||
} | ||
|
||
return p.Wait // return method value | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package gogrouptest_test | ||
|
||
import ( | ||
"context" | ||
"runtime" | ||
"sync" | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
"github.com/google/uuid" | ||
"github.com/newmo-oss/testid" | ||
"github.com/newmo-oss/gotestingmock" | ||
|
||
"github.com/newmo-oss/gogroup" | ||
"github.com/newmo-oss/gogroup/gogrouptest" | ||
) | ||
|
||
func TestWithoutParallel(t *testing.T) { | ||
t.Parallel() | ||
|
||
cases := map[string]struct { | ||
noParallel bool | ||
}{ | ||
"no parallel": {true}, | ||
"parallel": {false}, | ||
} | ||
|
||
for name, tt := range cases { | ||
t.Run(name, func(t *testing.T) { | ||
t.Parallel() | ||
var cleanedup bool | ||
t.Cleanup(func() { | ||
if tt.noParallel && !cleanedup { | ||
t.Error("t.Cleanup must be called") | ||
} | ||
}) | ||
|
||
var want, got []int | ||
var mu sync.Mutex | ||
var g gogroup.Group | ||
for i := range 100 { | ||
want = append(want, i) | ||
g.Add(func(ctx context.Context) error { | ||
if i%2 == 0 { | ||
runtime.Gosched() | ||
} | ||
mu.Lock() | ||
got = append(got, i) | ||
mu.Unlock() | ||
return nil | ||
}) | ||
} | ||
|
||
tid := t.Name() + "/" + uuid.NewString() | ||
ctx := testid.WithValue(context.Background(), tid) | ||
|
||
if tt.noParallel { | ||
tb := &gotestingmock.TB{ | ||
TB: t, | ||
CleanupFunc: func(f func()) { | ||
cleanedup = true | ||
t.Cleanup(f) | ||
}, | ||
} | ||
gogrouptest.WithoutParallel(tb, ctx) | ||
} | ||
|
||
if err := g.Run(ctx); err != nil { | ||
t.Fatal("unexpected error:", err) | ||
} | ||
|
||
diff := cmp.Diff(got, want) | ||
switch { | ||
case tt.noParallel && diff != "": | ||
t.Error("executing order does not match:", diff) | ||
case !tt.noParallel && diff == "": | ||
t.Error("executing order may be randodm") | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package internal | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/sourcegraph/conc/panics" | ||
"github.com/sourcegraph/conc/pool" | ||
) | ||
|
||
var Start = DefaultStart | ||
|
||
func DefaultStart(ctx context.Context, funcs []func(context.Context) error) func() error { | ||
p := pool.New().WithContext(ctx).WithCancelOnError() | ||
for _, f := range funcs { | ||
p.Go(func(ctx context.Context) (rerr error) { | ||
if r := panics.Try(func() { rerr = f(ctx) }); r != nil { | ||
return r.AsError() | ||
} | ||
return rerr | ||
}) | ||
} | ||
return p.Wait // return method value | ||
} |