源码索引 / CURRENT IMPLEMENTATION
learning/go-patterns/stages/05-parallel/main_test.go
80 行 · 点击行号可定位;函数链接随声明位置更新,不手填行号。
跳到函数 / 声明
package main
import (
"context"
"errors"
"testing"
"time"
)
func waitForSignal(t *testing.T, signal <-chan struct{}, name string) {
t.Helper()
select {
case <-signal:
case <-time.After(time.Second):
t.Fatalf("timed out waiting for %s", name)
}
}
func TestRunTwoStartsBothTasksBeforeCollectingResults(t *testing.T) {
firstStarted := make(chan struct{})
secondStarted := make(chan struct{})
release := make(chan struct{})
first := func(context.Context) (string, error) {
close(firstStarted)
<-release
return "first", nil
}
second := func(context.Context) (string, error) {
close(secondStarted)
<-release
return "second", nil
}
done := make(chan struct{})
var values [2]string
var err error
go func() {
values, err = RunTwo(context.Background(), first, second)
close(done)
}()
waitForSignal(t, firstStarted, "first task to start")
waitForSignal(t, secondStarted, "second task to start")
close(release)
waitForSignal(t, done, "RunTwo to return")
if err != nil {
t.Fatalf("RunTwo returned error: %v", err)
}
if values != [2]string{"first", "second"} {
t.Fatalf("results = %#v, want [first second]", values)
}
}
func TestRunTwoWaitsForTheOtherTaskAfterAnError(t *testing.T) {
wantErr := errors.New("first task failed")
secondDone := make(chan struct{})
values, err := RunTwo(
context.Background(),
func(context.Context) (string, error) { return "", wantErr },
func(context.Context) (string, error) {
close(secondDone)
return "second", nil
},
)
if !errors.Is(err, wantErr) {
t.Fatalf("error = %v, want %v", err, wantErr)
}
select {
case <-secondDone:
default:
t.Fatal("RunTwo returned before the second task completed")
}
if values[1] != "second" {
t.Fatalf("second result = %q, want %q", values[1], "second")
}
}