type B struct {
common
importPath string // import path of the package containing the benchmark
- context *benchContext
+ bstate *benchState
N int
previousN int // number of iterations in the previous run
previousDuration time.Duration // total duration of the previous run
// run1 runs the first iteration of benchFunc. It reports whether more
// iterations of this benchmarks should be run.
func (b *B) run1() bool {
- if ctx := b.context; ctx != nil {
+ if bstate := b.bstate; bstate != nil {
// Extend maxLen, if needed.
- if n := len(b.name) + ctx.extLen + 1; n > ctx.maxLen {
- ctx.maxLen = n + 8 // Add additional slack to avoid too many jumps in size.
+ if n := len(b.name) + bstate.extLen + 1; n > bstate.maxLen {
+ bstate.maxLen = n + 8 // Add additional slack to avoid too many jumps in size.
}
}
go func() {
fmt.Fprintf(b.w, "cpu: %s\n", cpu)
}
})
- if b.context != nil {
+ if b.bstate != nil {
// Running go test --test.bench
- b.context.processBench(b) // Must call doBench.
+ b.bstate.processBench(b) // Must call doBench.
} else {
// Running func Benchmark.
b.doBench()
return name
}
-type benchContext struct {
+type benchState struct {
match *matcher
maxLen int // The largest recorded benchmark name.
maxprocs = procs
}
}
- ctx := &benchContext{
+ bstate := &benchState{
match: newMatcher(matchString, *matchBenchmarks, "-test.bench", *skip),
extLen: len(benchmarkName("", maxprocs)),
}
var bs []InternalBenchmark
for _, Benchmark := range benchmarks {
- if _, matched, _ := ctx.match.fullName(nil, Benchmark.Name); matched {
+ if _, matched, _ := bstate.match.fullName(nil, Benchmark.Name); matched {
bs = append(bs, Benchmark)
benchName := benchmarkName(Benchmark.Name, maxprocs)
- if l := len(benchName) + ctx.extLen + 1; l > ctx.maxLen {
- ctx.maxLen = l
+ if l := len(benchName) + bstate.extLen + 1; l > bstate.maxLen {
+ bstate.maxLen = l
}
}
}
}
},
benchTime: benchTime,
- context: ctx,
+ bstate: bstate,
}
if Verbose() {
main.chatty = newChattyPrinter(main.w)
}
// processBench runs bench b for the configured CPU counts and prints the results.
-func (ctx *benchContext) processBench(b *B) {
+func (s *benchState) processBench(b *B) {
for i, procs := range cpuList {
for j := uint(0); j < *count; j++ {
runtime.GOMAXPROCS(procs)
// If it's chatty, we've already printed this information.
if b.chatty == nil {
- fmt.Fprintf(b.w, "%-*s\t", ctx.maxLen, benchName)
+ fmt.Fprintf(b.w, "%-*s\t", s.maxLen, benchName)
}
// Recompute the running time for all but the first iteration.
if i > 0 || j > 0 {
}
results := r.String()
if b.chatty != nil {
- fmt.Fprintf(b.w, "%-*s\t", ctx.maxLen, benchName)
+ fmt.Fprintf(b.w, "%-*s\t", s.maxLen, benchName)
}
if *benchmarkMemory || b.showAllocResult {
results += "\t" + r.MemString()
defer benchmarkLock.Lock()
benchName, ok, partial := b.name, true, false
- if b.context != nil {
- benchName, ok, partial = b.context.match.fullName(&b.common, name)
+ if b.bstate != nil {
+ benchName, ok, partial = b.bstate.match.fullName(&b.common, name)
}
if !ok {
return true
importPath: b.importPath,
benchFunc: f,
benchTime: b.benchTime,
- context: b.context,
+ bstate: b.bstate,
}
if partial {
// Partial name match, like -bench=X/Y matching BenchmarkX.
// that are allowed in the (*F).Fuzz function are (*F).Failed and (*F).Name.
type F struct {
common
- fuzzContext *fuzzContext
- testContext *testContext
+ fstate *fuzzState
+ tstate *testState
// inFuzzFn is true when the fuzz function is running. Most F methods cannot
// be called when inFuzzFn is true.
// corpus and entries declared with F.Add.
//
// Don't load the seed corpus if this is a worker process; we won't use it.
- if f.fuzzContext.mode != fuzzWorker {
+ if f.fstate.mode != fuzzWorker {
for _, c := range f.corpus {
- if err := f.fuzzContext.deps.CheckCorpus(c.Values, types); err != nil {
+ if err := f.fstate.deps.CheckCorpus(c.Values, types); err != nil {
// TODO(#48302): Report the source location of the F.Add call.
f.Fatal(err)
}
}
// Load seed corpus
- c, err := f.fuzzContext.deps.ReadCorpus(filepath.Join(corpusDir, f.name), types)
+ c, err := f.fstate.deps.ReadCorpus(filepath.Join(corpusDir, f.name), types)
if err != nil {
f.Fatal(err)
}
for i := range c {
c[i].IsSeed = true // these are all seed corpus values
- if f.fuzzContext.mode == fuzzCoordinator {
+ if f.fstate.mode == fuzzCoordinator {
// If this is the coordinator process, zero the values, since we don't need
// to hold onto them.
c[i].Values = nil
if e.Path != "" {
testName = fmt.Sprintf("%s/%s", testName, filepath.Base(e.Path))
}
- if f.testContext.isFuzzing {
+ if f.tstate.isFuzzing {
// Don't preserve subtest names while fuzzing. If fn calls T.Run,
// there will be a very large number of subtests with duplicate names,
// which will use a large amount of memory. The subtest names aren't
// useful since there's no way to re-run them deterministically.
- f.testContext.match.clearSubNames()
+ f.tstate.match.clearSubNames()
}
// Record the stack trace at the point of this call so that if the subtest
creator: pc[:n],
chatty: f.chatty,
},
- context: f.testContext,
+ tstate: f.tstate,
}
if captureOut != nil {
// t.parent aliases f.common.
// we make sure it is called right before the tRunner function
// exits, regardless of whether it was executed cleanly, panicked,
// or if the fuzzFn called t.Fatal.
- if f.testContext.isFuzzing {
- defer f.fuzzContext.deps.SnapshotCoverage()
- f.fuzzContext.deps.ResetCoverage()
+ if f.tstate.isFuzzing {
+ defer f.fstate.deps.SnapshotCoverage()
+ f.fstate.deps.ResetCoverage()
}
fn.Call(args)
})
return !t.Failed()
}
- switch f.fuzzContext.mode {
+ switch f.fstate.mode {
case fuzzCoordinator:
// Fuzzing is enabled, and this is the test process started by 'go test'.
// Act as the coordinator process, and coordinate workers to perform the
// actual fuzzing.
corpusTargetDir := filepath.Join(corpusDir, f.name)
cacheTargetDir := filepath.Join(*fuzzCacheDir, f.name)
- err := f.fuzzContext.deps.CoordinateFuzzing(
+ err := f.fstate.deps.CoordinateFuzzing(
fuzzDuration.d,
int64(fuzzDuration.n),
minimizeDuration.d,
case fuzzWorker:
// Fuzzing is enabled, and this is a worker process. Follow instructions
// from the coordinator.
- if err := f.fuzzContext.deps.RunFuzzWorker(func(e corpusEntry) error {
+ if err := f.fstate.deps.RunFuzzWorker(func(e corpusEntry) error {
// Don't write to f.w (which points to Stdout) if running from a
// fuzz worker. This would become very verbose, particularly during
// minimization. Return the error instead, and let the caller deal
// corpus now.
for _, e := range f.corpus {
name := fmt.Sprintf("%s/%s", f.name, filepath.Base(e.Path))
- if _, ok, _ := f.testContext.match.fullName(nil, name); ok {
+ if _, ok, _ := f.tstate.match.fullName(nil, name); ok {
run(f.w, e)
}
}
CrashPath() string
}
-// fuzzContext holds fields common to all fuzz tests.
-type fuzzContext struct {
+// fuzzState holds fields common to all fuzz tests.
+type fuzzState struct {
deps testDeps
mode fuzzMode
}
break
}
- tctx := newTestContext(*parallel, m)
- tctx.deadline = deadline
- fctx := &fuzzContext{deps: deps, mode: seedCorpusOnly}
+ tstate := newTestState(*parallel, m)
+ tstate.deadline = deadline
+ fstate := &fuzzState{deps: deps, mode: seedCorpusOnly}
root := common{w: os.Stdout} // gather output in one place
if Verbose() {
root.chatty = newChattyPrinter(root.w)
if shouldFailFast() {
break
}
- testName, matched, _ := tctx.match.fullName(nil, ft.Name)
+ testName, matched, _ := tstate.match.fullName(nil, ft.Name)
if !matched {
continue
}
level: root.level + 1,
chatty: root.chatty,
},
- testContext: tctx,
- fuzzContext: fctx,
+ tstate: tstate,
+ fstate: fstate,
}
f.w = indenter{&f.common}
if f.chatty != nil {
return true
}
m := newMatcher(deps.MatchString, *matchFuzz, "-test.fuzz", *skip)
- tctx := newTestContext(1, m)
- tctx.isFuzzing = true
- fctx := &fuzzContext{
+ tstate := newTestState(1, m)
+ tstate.isFuzzing = true
+ fstate := &fuzzState{
deps: deps,
}
root := common{w: os.Stdout}
if *isFuzzWorker {
root.w = io.Discard
- fctx.mode = fuzzWorker
+ fstate.mode = fuzzWorker
} else {
- fctx.mode = fuzzCoordinator
+ fstate.mode = fuzzCoordinator
}
if Verbose() && !*isFuzzWorker {
root.chatty = newChattyPrinter(root.w)
var testName string
var matched []string
for i := range fuzzTests {
- name, ok, _ := tctx.match.fullName(nil, fuzzTests[i].Name)
+ name, ok, _ := tstate.match.fullName(nil, fuzzTests[i].Name)
if !ok {
continue
}
level: root.level + 1,
chatty: root.chatty,
},
- fuzzContext: fctx,
- testContext: tctx,
+ fstate: fstate,
+ tstate: tstate,
}
f.w = indenter{&f.common}
if f.chatty != nil {
// This only affects fuzz tests run as normal tests.
// While fuzzing, T.Parallel has no effect, so f.sub is empty, and this
// branch is not taken. f.barrier is nil in that case.
- f.testContext.release()
+ f.tstate.release()
close(f.barrier)
// Wait for the subtests to complete.
for _, sub := range f.sub {
benchTime.d = 100 * time.Millisecond
}
-func TestTestContext(t *T) {
+func TestTestState(t *T) {
const (
add1 = 0
done = 1
)
- // After each of the calls are applied to the context, the
type call struct {
typ int // run or done
// result from applying the call
},
}}
for i, tc := range testCases {
- ctx := &testContext{
+ tstate := &testState{
startParallel: make(chan bool),
maxParallel: tc.max,
}
started := false
switch call.typ {
case add1:
- signal := doCall(ctx.waitParallel)
+ signal := doCall(tstate.waitParallel)
select {
case <-signal:
started = true
- case ctx.startParallel <- true:
+ case tstate.startParallel <- true:
<-signal
}
case done:
- signal := doCall(ctx.release)
+ signal := doCall(tstate.release)
select {
case <-signal:
- case <-ctx.startParallel:
+ case <-tstate.startParallel:
started = true
<-signal
}
if started != call.started {
t.Errorf("%d:%d:started: got %v; want %v", i, j, started, call.started)
}
- if ctx.running != call.running {
- t.Errorf("%d:%d:running: got %v; want %v", i, j, ctx.running, call.running)
+ if tstate.running != call.running {
+ t.Errorf("%d:%d:running: got %v; want %v", i, j, tstate.running, call.running)
}
- if ctx.numWaiting != call.waiting {
- t.Errorf("%d:%d:waiting: got %v; want %v", i, j, ctx.numWaiting, call.waiting)
+ if tstate.numWaiting != call.waiting {
+ t.Errorf("%d:%d:waiting: got %v; want %v", i, j, tstate.numWaiting, call.waiting)
}
}
}
}}
for _, tc := range testCases {
t.Run(tc.desc, func(t *T) {
- ctx := newTestContext(tc.maxPar, allMatcher())
+ tstate := newTestState(tc.maxPar, allMatcher())
buf := &strings.Builder{}
root := &T{
common: common{
name: "",
w: buf,
},
- context: ctx,
+ tstate: tstate,
}
if tc.chatty {
root.chatty = newChattyPrinter(root.w)
root.chatty.json = tc.json
}
ok := root.Run(tc.desc, tc.f)
- ctx.release()
+ tstate.release()
if ok != tc.ok {
t.Errorf("%s:ok: got %v; want %v", tc.desc, ok, tc.ok)
if ok != !root.Failed() {
t.Errorf("%s:root failed: got %v; want %v", tc.desc, !ok, root.Failed())
}
- if ctx.running != 0 || ctx.numWaiting != 0 {
- t.Errorf("%s:running and waiting non-zero: got %d and %d", tc.desc, ctx.running, ctx.numWaiting)
+ if tstate.running != 0 || tstate.numWaiting != 0 {
+ t.Errorf("%s:running and waiting non-zero: got %d and %d", tc.desc, tstate.running, tstate.numWaiting)
}
got := strings.TrimSpace(buf.String())
want := strings.TrimSpace(tc.output)
}
root := &T{
- common: common{w: &funcWriter{raceDetector}},
- context: newTestContext(1, allMatcher()),
+ common: common{w: &funcWriter{raceDetector}},
+ tstate: newTestState(1, allMatcher()),
}
root.chatty = newChattyPrinter(root.w)
root.Run("", func(t *T) {
// The late log message did not include the test name. Issue 29388.
func TestLogAfterComplete(t *T) {
- ctx := newTestContext(1, allMatcher())
+ tstate := newTestState(1, allMatcher())
var buf bytes.Buffer
t1 := &T{
common: common{
signal: make(chan bool, 1),
w: &buf,
},
- context: ctx,
+ tstate: tstate,
}
c1 := make(chan bool)
type T struct {
common
denyParallel bool
- context *testContext // For running tests and subtests.
+ tstate *testState // For running tests and subtests.
}
func (c *common) private() {}
t.signal <- true // Release calling test.
<-t.parent.barrier // Wait for the parent test to complete.
- t.context.waitParallel()
+ t.tstate.waitParallel()
if t.chatty != nil {
t.chatty.Updatef(t.name, "=== CONT %s\n", t.name)
}
}
- if err != nil && t.context.isFuzzing {
+ if err != nil && t.tstate.isFuzzing {
prefix := "panic: "
if err == errNilPanicOrGoexit {
prefix = ""
// Run parallel subtests.
// Decrease the running count for this test and mark it as no longer running.
- t.context.release()
+ t.tstate.release()
running.Delete(t.name)
// Release the parallel subtests.
t.checkRaces()
if !t.isParallel {
// Reacquire the count for sequential tests. See comment in Run.
- t.context.waitParallel()
+ t.tstate.waitParallel()
}
} else if t.isParallel {
// Only release the count for this test if it was run as a parallel
// test. See comment in Run method.
- t.context.release()
+ t.tstate.release()
}
t.report() // Report after all subtests have finished.
}
t.hasSub.Store(true)
- testName, ok, _ := t.context.match.fullName(&t.common, name)
+ testName, ok, _ := t.tstate.match.fullName(&t.common, name)
if !ok || shouldFailFast() {
return true
}
ctx: ctx,
cancelCtx: cancelCtx,
},
- context: t.context,
+ tstate: t.tstate,
}
t.w = indenter{&t.common}
//
// The ok result is false if the -timeout flag indicates “no timeout” (0).
func (t *T) Deadline() (deadline time.Time, ok bool) {
- deadline = t.context.deadline
+ deadline = t.tstate.deadline
return deadline, !deadline.IsZero()
}
-// testContext holds all fields that are common to all tests. This includes
+// testState holds all fields that are common to all tests. This includes
// synchronization primitives to run at most *parallel tests.
-type testContext struct {
+type testState struct {
match *matcher
deadline time.Time
- // isFuzzing is true in the context used when generating random inputs
+ // isFuzzing is true in the state used when generating random inputs
// for fuzz targets. isFuzzing is false when running normal tests and
// when running fuzz tests as unit tests (without -fuzz or when -fuzz
// does not match).
maxParallel int
}
-func newTestContext(maxParallel int, m *matcher) *testContext {
- return &testContext{
+func newTestState(maxParallel int, m *matcher) *testState {
+ return &testState{
match: m,
startParallel: make(chan bool),
maxParallel: maxParallel,
}
}
-func (c *testContext) waitParallel() {
- c.mu.Lock()
- if c.running < c.maxParallel {
- c.running++
- c.mu.Unlock()
+func (s *testState) waitParallel() {
+ s.mu.Lock()
+ if s.running < s.maxParallel {
+ s.running++
+ s.mu.Unlock()
return
}
- c.numWaiting++
- c.mu.Unlock()
- <-c.startParallel
+ s.numWaiting++
+ s.mu.Unlock()
+ <-s.startParallel
}
-func (c *testContext) release() {
- c.mu.Lock()
- if c.numWaiting == 0 {
- c.running--
- c.mu.Unlock()
+func (s *testState) release() {
+ s.mu.Lock()
+ if s.numWaiting == 0 {
+ s.running--
+ s.mu.Unlock()
return
}
- c.numWaiting--
- c.mu.Unlock()
- c.startParallel <- true // Pick a waiting test to be run.
+ s.numWaiting--
+ s.mu.Unlock()
+ s.startParallel <- true // Pick a waiting test to be run.
}
// No one should be using func Main anymore.
break
}
ctx, cancelCtx := context.WithCancel(context.Background())
- tctx := newTestContext(*parallel, newMatcher(matchString, *match, "-test.run", *skip))
- tctx.deadline = deadline
+ tstate := newTestState(*parallel, newMatcher(matchString, *match, "-test.run", *skip))
+ tstate.deadline = deadline
t := &T{
common: common{
signal: make(chan bool, 1),
ctx: ctx,
cancelCtx: cancelCtx,
},
- context: tctx,
+ tstate: tstate,
}
if Verbose() {
t.chatty = newChattyPrinter(t.w)