github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/testing/sub_test.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package testing
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"reflect"
    11  	"regexp"
    12  	"runtime"
    13  	"strings"
    14  	"sync"
    15  	"sync/atomic"
    16  	"time"
    17  )
    18  
    19  func init() {
    20  	// Make benchmark tests run 10x faster.
    21  	benchTime.d = 100 * time.Millisecond
    22  }
    23  
    24  func TestTestContext(t *T) {
    25  	const (
    26  		add1 = 0
    27  		done = 1
    28  	)
    29  	// After each of the calls are applied to the context, the
    30  	type call struct {
    31  		typ int // run or done
    32  		// result from applying the call
    33  		running int
    34  		waiting int
    35  		started bool
    36  	}
    37  	testCases := []struct {
    38  		max int
    39  		run []call
    40  	}{{
    41  		max: 1,
    42  		run: []call{
    43  			{typ: add1, running: 1, waiting: 0, started: true},
    44  			{typ: done, running: 0, waiting: 0, started: false},
    45  		},
    46  	}, {
    47  		max: 1,
    48  		run: []call{
    49  			{typ: add1, running: 1, waiting: 0, started: true},
    50  			{typ: add1, running: 1, waiting: 1, started: false},
    51  			{typ: done, running: 1, waiting: 0, started: true},
    52  			{typ: done, running: 0, waiting: 0, started: false},
    53  			{typ: add1, running: 1, waiting: 0, started: true},
    54  		},
    55  	}, {
    56  		max: 3,
    57  		run: []call{
    58  			{typ: add1, running: 1, waiting: 0, started: true},
    59  			{typ: add1, running: 2, waiting: 0, started: true},
    60  			{typ: add1, running: 3, waiting: 0, started: true},
    61  			{typ: add1, running: 3, waiting: 1, started: false},
    62  			{typ: add1, running: 3, waiting: 2, started: false},
    63  			{typ: add1, running: 3, waiting: 3, started: false},
    64  			{typ: done, running: 3, waiting: 2, started: true},
    65  			{typ: add1, running: 3, waiting: 3, started: false},
    66  			{typ: done, running: 3, waiting: 2, started: true},
    67  			{typ: done, running: 3, waiting: 1, started: true},
    68  			{typ: done, running: 3, waiting: 0, started: true},
    69  			{typ: done, running: 2, waiting: 0, started: false},
    70  			{typ: done, running: 1, waiting: 0, started: false},
    71  			{typ: done, running: 0, waiting: 0, started: false},
    72  		},
    73  	}}
    74  	for i, tc := range testCases {
    75  		ctx := &testContext{
    76  			startParallel: make(chan bool),
    77  			maxParallel:   tc.max,
    78  		}
    79  		for j, call := range tc.run {
    80  			doCall := func(f func()) chan bool {
    81  				done := make(chan bool)
    82  				go func() {
    83  					f()
    84  					done <- true
    85  				}()
    86  				return done
    87  			}
    88  			started := false
    89  			switch call.typ {
    90  			case add1:
    91  				signal := doCall(ctx.waitParallel)
    92  				select {
    93  				case <-signal:
    94  					started = true
    95  				case ctx.startParallel <- true:
    96  					<-signal
    97  				}
    98  			case done:
    99  				signal := doCall(ctx.release)
   100  				select {
   101  				case <-signal:
   102  				case <-ctx.startParallel:
   103  					started = true
   104  					<-signal
   105  				}
   106  			}
   107  			if started != call.started {
   108  				t.Errorf("%d:%d:started: got %v; want %v", i, j, started, call.started)
   109  			}
   110  			if ctx.running != call.running {
   111  				t.Errorf("%d:%d:running: got %v; want %v", i, j, ctx.running, call.running)
   112  			}
   113  			if ctx.numWaiting != call.waiting {
   114  				t.Errorf("%d:%d:waiting: got %v; want %v", i, j, ctx.numWaiting, call.waiting)
   115  			}
   116  		}
   117  	}
   118  }
   119  
   120  func TestTRun(t *T) {
   121  	realTest := t
   122  	testCases := []struct {
   123  		desc   string
   124  		ok     bool
   125  		maxPar int
   126  		chatty bool
   127  		output string
   128  		f      func(*T)
   129  	}{{
   130  		desc:   "failnow skips future sequential and parallel tests at same level",
   131  		ok:     false,
   132  		maxPar: 1,
   133  		output: `
   134  --- FAIL: failnow skips future sequential and parallel tests at same level (N.NNs)
   135      --- FAIL: failnow skips future sequential and parallel tests at same level/#00 (N.NNs)
   136      `,
   137  		f: func(t *T) {
   138  			ranSeq := false
   139  			ranPar := false
   140  			t.Run("", func(t *T) {
   141  				t.Run("par", func(t *T) {
   142  					t.Parallel()
   143  					ranPar = true
   144  				})
   145  				t.Run("seq", func(t *T) {
   146  					ranSeq = true
   147  				})
   148  				t.FailNow()
   149  				t.Run("seq", func(t *T) {
   150  					realTest.Error("test must be skipped")
   151  				})
   152  				t.Run("par", func(t *T) {
   153  					t.Parallel()
   154  					realTest.Error("test must be skipped.")
   155  				})
   156  			})
   157  			if !ranPar {
   158  				realTest.Error("parallel test was not run")
   159  			}
   160  			if !ranSeq {
   161  				realTest.Error("sequential test was not run")
   162  			}
   163  		},
   164  	}, {
   165  		desc:   "failure in parallel test propagates upwards",
   166  		ok:     false,
   167  		maxPar: 1,
   168  		output: `
   169  --- FAIL: failure in parallel test propagates upwards (N.NNs)
   170      --- FAIL: failure in parallel test propagates upwards/#00 (N.NNs)
   171          --- FAIL: failure in parallel test propagates upwards/#00/par (N.NNs)
   172          `,
   173  		f: func(t *T) {
   174  			t.Run("", func(t *T) {
   175  				t.Parallel()
   176  				t.Run("par", func(t *T) {
   177  					t.Parallel()
   178  					t.Fail()
   179  				})
   180  			})
   181  		},
   182  	}, {
   183  		desc:   "skipping without message, chatty",
   184  		ok:     true,
   185  		chatty: true,
   186  		output: `
   187  === RUN   skipping without message, chatty
   188  --- SKIP: skipping without message, chatty (N.NNs)`,
   189  		f: func(t *T) { t.SkipNow() },
   190  	}, {
   191  		desc:   "chatty with recursion",
   192  		ok:     true,
   193  		chatty: true,
   194  		output: `
   195  === RUN   chatty with recursion
   196  === RUN   chatty with recursion/#00
   197  === RUN   chatty with recursion/#00/#00
   198  --- PASS: chatty with recursion (N.NNs)
   199      --- PASS: chatty with recursion/#00 (N.NNs)
   200          --- PASS: chatty with recursion/#00/#00 (N.NNs)`,
   201  		f: func(t *T) {
   202  			t.Run("", func(t *T) {
   203  				t.Run("", func(t *T) {})
   204  			})
   205  		},
   206  	}, {
   207  		desc: "skipping without message, not chatty",
   208  		ok:   true,
   209  		f:    func(t *T) { t.SkipNow() },
   210  	}, {
   211  		desc: "skipping after error",
   212  		output: `
   213  --- FAIL: skipping after error (N.NNs)
   214      sub_test.go:NNN: an error
   215      sub_test.go:NNN: skipped`,
   216  		f: func(t *T) {
   217  			t.Error("an error")
   218  			t.Skip("skipped")
   219  		},
   220  	}, {
   221  		desc:   "use Run to locally synchronize parallelism",
   222  		ok:     true,
   223  		maxPar: 1,
   224  		f: func(t *T) {
   225  			var count uint32
   226  			t.Run("waitGroup", func(t *T) {
   227  				for i := 0; i < 4; i++ {
   228  					t.Run("par", func(t *T) {
   229  						t.Parallel()
   230  						atomic.AddUint32(&count, 1)
   231  					})
   232  				}
   233  			})
   234  			if count != 4 {
   235  				t.Errorf("count was %d; want 4", count)
   236  			}
   237  		},
   238  	}, {
   239  		desc: "alternate sequential and parallel",
   240  		// Sequential tests should partake in the counting of running threads.
   241  		// Otherwise, if one runs parallel subtests in sequential tests that are
   242  		// itself subtests of parallel tests, the counts can get askew.
   243  		ok:     true,
   244  		maxPar: 1,
   245  		f: func(t *T) {
   246  			t.Run("a", func(t *T) {
   247  				t.Parallel()
   248  				t.Run("b", func(t *T) {
   249  					// Sequential: ensure running count is decremented.
   250  					t.Run("c", func(t *T) {
   251  						t.Parallel()
   252  					})
   253  
   254  				})
   255  			})
   256  		},
   257  	}, {
   258  		desc: "alternate sequential and parallel 2",
   259  		// Sequential tests should partake in the counting of running threads.
   260  		// Otherwise, if one runs parallel subtests in sequential tests that are
   261  		// itself subtests of parallel tests, the counts can get askew.
   262  		ok:     true,
   263  		maxPar: 2,
   264  		f: func(t *T) {
   265  			for i := 0; i < 2; i++ {
   266  				t.Run("a", func(t *T) {
   267  					t.Parallel()
   268  					time.Sleep(time.Nanosecond)
   269  					for i := 0; i < 2; i++ {
   270  						t.Run("b", func(t *T) {
   271  							time.Sleep(time.Nanosecond)
   272  							for i := 0; i < 2; i++ {
   273  								t.Run("c", func(t *T) {
   274  									t.Parallel()
   275  									time.Sleep(time.Nanosecond)
   276  								})
   277  							}
   278  
   279  						})
   280  					}
   281  				})
   282  			}
   283  		},
   284  	}, {
   285  		desc:   "stress test",
   286  		ok:     true,
   287  		maxPar: 4,
   288  		f: func(t *T) {
   289  			t.Parallel()
   290  			for i := 0; i < 12; i++ {
   291  				t.Run("a", func(t *T) {
   292  					t.Parallel()
   293  					time.Sleep(time.Nanosecond)
   294  					for i := 0; i < 12; i++ {
   295  						t.Run("b", func(t *T) {
   296  							time.Sleep(time.Nanosecond)
   297  							for i := 0; i < 12; i++ {
   298  								t.Run("c", func(t *T) {
   299  									t.Parallel()
   300  									time.Sleep(time.Nanosecond)
   301  									t.Run("d1", func(t *T) {})
   302  									t.Run("d2", func(t *T) {})
   303  									t.Run("d3", func(t *T) {})
   304  									t.Run("d4", func(t *T) {})
   305  								})
   306  							}
   307  						})
   308  					}
   309  				})
   310  			}
   311  		},
   312  	}, {
   313  		desc:   "skip output",
   314  		ok:     true,
   315  		maxPar: 4,
   316  		f: func(t *T) {
   317  			t.Skip()
   318  		},
   319  	}, {
   320  		desc: "subtest calls error on parent",
   321  		ok:   false,
   322  		output: `
   323  --- FAIL: subtest calls error on parent (N.NNs)
   324      sub_test.go:NNN: first this
   325      sub_test.go:NNN: and now this!
   326      sub_test.go:NNN: oh, and this too`,
   327  		maxPar: 1,
   328  		f: func(t *T) {
   329  			t.Errorf("first this")
   330  			outer := t
   331  			t.Run("", func(t *T) {
   332  				outer.Errorf("and now this!")
   333  			})
   334  			t.Errorf("oh, and this too")
   335  		},
   336  	}, {
   337  		desc: "subtest calls fatal on parent",
   338  		ok:   false,
   339  		output: `
   340  --- FAIL: subtest calls fatal on parent (N.NNs)
   341      sub_test.go:NNN: first this
   342      sub_test.go:NNN: and now this!
   343      --- FAIL: subtest calls fatal on parent/#00 (N.NNs)
   344          testing.go:NNN: test executed panic(nil) or runtime.Goexit: subtest may have called FailNow on a parent test`,
   345  		maxPar: 1,
   346  		f: func(t *T) {
   347  			outer := t
   348  			t.Errorf("first this")
   349  			t.Run("", func(t *T) {
   350  				outer.Fatalf("and now this!")
   351  			})
   352  			t.Errorf("Should not reach here.")
   353  		},
   354  	}, {
   355  		desc: "subtest calls error on ancestor",
   356  		ok:   false,
   357  		output: `
   358  --- FAIL: subtest calls error on ancestor (N.NNs)
   359      sub_test.go:NNN: Report to ancestor
   360      --- FAIL: subtest calls error on ancestor/#00 (N.NNs)
   361          sub_test.go:NNN: Still do this
   362      sub_test.go:NNN: Also do this`,
   363  		maxPar: 1,
   364  		f: func(t *T) {
   365  			outer := t
   366  			t.Run("", func(t *T) {
   367  				t.Run("", func(t *T) {
   368  					outer.Errorf("Report to ancestor")
   369  				})
   370  				t.Errorf("Still do this")
   371  			})
   372  			t.Errorf("Also do this")
   373  		},
   374  	}, {
   375  		desc: "subtest calls fatal on ancestor",
   376  		ok:   false,
   377  		output: `
   378  --- FAIL: subtest calls fatal on ancestor (N.NNs)
   379      sub_test.go:NNN: Nope`,
   380  		maxPar: 1,
   381  		f: func(t *T) {
   382  			outer := t
   383  			t.Run("", func(t *T) {
   384  				for i := 0; i < 4; i++ {
   385  					t.Run("", func(t *T) {
   386  						outer.Fatalf("Nope")
   387  					})
   388  					t.Errorf("Don't do this")
   389  				}
   390  				t.Errorf("And neither do this")
   391  			})
   392  			t.Errorf("Nor this")
   393  		},
   394  	}, {
   395  		desc:   "panic on goroutine fail after test exit",
   396  		ok:     false,
   397  		maxPar: 4,
   398  		f: func(t *T) {
   399  			ch := make(chan bool)
   400  			t.Run("", func(t *T) {
   401  				go func() {
   402  					<-ch
   403  					defer func() {
   404  						if r := recover(); r == nil {
   405  							realTest.Errorf("expected panic")
   406  						}
   407  						ch <- true
   408  					}()
   409  					t.Errorf("failed after success")
   410  				}()
   411  			})
   412  			ch <- true
   413  			<-ch
   414  		},
   415  	}, {
   416  		desc: "log in finished sub test logs to parent",
   417  		ok:   false,
   418  		output: `
   419  		--- FAIL: log in finished sub test logs to parent (N.NNs)
   420      sub_test.go:NNN: message2
   421      sub_test.go:NNN: message1
   422      sub_test.go:NNN: error`,
   423  		maxPar: 1,
   424  		f: func(t *T) {
   425  			ch := make(chan bool)
   426  			t.Run("sub", func(t2 *T) {
   427  				go func() {
   428  					<-ch
   429  					t2.Log("message1")
   430  					ch <- true
   431  				}()
   432  			})
   433  			t.Log("message2")
   434  			ch <- true
   435  			<-ch
   436  			t.Errorf("error")
   437  		},
   438  	}, {
   439  		// A chatty test should always log with fmt.Print, even if the
   440  		// parent test has completed.
   441  		desc:   "log in finished sub test with chatty",
   442  		ok:     false,
   443  		chatty: true,
   444  		output: `
   445  		--- FAIL: log in finished sub test with chatty (N.NNs)`,
   446  		maxPar: 1,
   447  		f: func(t *T) {
   448  			ch := make(chan bool)
   449  			t.Run("sub", func(t2 *T) {
   450  				go func() {
   451  					<-ch
   452  					t2.Log("message1")
   453  					ch <- true
   454  				}()
   455  			})
   456  			t.Log("message2")
   457  			ch <- true
   458  			<-ch
   459  			t.Errorf("error")
   460  		},
   461  	}, {
   462  		// If a subtest panics we should run cleanups.
   463  		desc:   "cleanup when subtest panics",
   464  		ok:     false,
   465  		chatty: false,
   466  		output: `
   467  --- FAIL: cleanup when subtest panics (N.NNs)
   468      --- FAIL: cleanup when subtest panics/sub (N.NNs)
   469      sub_test.go:NNN: running cleanup`,
   470  		f: func(t *T) {
   471  			t.Cleanup(func() { t.Log("running cleanup") })
   472  			t.Run("sub", func(t2 *T) {
   473  				t2.FailNow()
   474  			})
   475  		},
   476  	}}
   477  	for _, tc := range testCases {
   478  		t.Run(tc.desc, func(t *T) {
   479  			ctx := newTestContext(tc.maxPar, allMatcher())
   480  			buf := &strings.Builder{}
   481  			root := &T{
   482  				common: common{
   483  					signal:  make(chan bool),
   484  					barrier: make(chan bool),
   485  					name:    "Test",
   486  					w:       buf,
   487  				},
   488  				context: ctx,
   489  			}
   490  			if tc.chatty {
   491  				root.chatty = newChattyPrinter(root.w)
   492  			}
   493  			ok := root.Run(tc.desc, tc.f)
   494  			ctx.release()
   495  
   496  			if ok != tc.ok {
   497  				t.Errorf("%s:ok: got %v; want %v", tc.desc, ok, tc.ok)
   498  			}
   499  			if ok != !root.Failed() {
   500  				t.Errorf("%s:root failed: got %v; want %v", tc.desc, !ok, root.Failed())
   501  			}
   502  			if ctx.running != 0 || ctx.numWaiting != 0 {
   503  				t.Errorf("%s:running and waiting non-zero: got %d and %d", tc.desc, ctx.running, ctx.numWaiting)
   504  			}
   505  			got := strings.TrimSpace(buf.String())
   506  			want := strings.TrimSpace(tc.output)
   507  			re := makeRegexp(want)
   508  			if ok, err := regexp.MatchString(re, got); !ok || err != nil {
   509  				t.Errorf("%s:output:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
   510  			}
   511  		})
   512  	}
   513  }
   514  
   515  func TestBRun(t *T) {
   516  	work := func(b *B) {
   517  		for i := 0; i < b.N; i++ {
   518  			time.Sleep(time.Nanosecond)
   519  		}
   520  	}
   521  	testCases := []struct {
   522  		desc   string
   523  		failed bool
   524  		chatty bool
   525  		output string
   526  		f      func(*B)
   527  	}{{
   528  		desc: "simulate sequential run of subbenchmarks.",
   529  		f: func(b *B) {
   530  			b.Run("", func(b *B) { work(b) })
   531  			time1 := b.result.NsPerOp()
   532  			b.Run("", func(b *B) { work(b) })
   533  			time2 := b.result.NsPerOp()
   534  			if time1 >= time2 {
   535  				t.Errorf("no time spent in benchmark t1 >= t2 (%d >= %d)", time1, time2)
   536  			}
   537  		},
   538  	}, {
   539  		desc: "bytes set by all benchmarks",
   540  		f: func(b *B) {
   541  			b.Run("", func(b *B) { b.SetBytes(10); work(b) })
   542  			b.Run("", func(b *B) { b.SetBytes(10); work(b) })
   543  			if b.result.Bytes != 20 {
   544  				t.Errorf("bytes: got: %d; want 20", b.result.Bytes)
   545  			}
   546  		},
   547  	}, {
   548  		desc: "bytes set by some benchmarks",
   549  		// In this case the bytes result is meaningless, so it must be 0.
   550  		f: func(b *B) {
   551  			b.Run("", func(b *B) { b.SetBytes(10); work(b) })
   552  			b.Run("", func(b *B) { work(b) })
   553  			b.Run("", func(b *B) { b.SetBytes(10); work(b) })
   554  			if b.result.Bytes != 0 {
   555  				t.Errorf("bytes: got: %d; want 0", b.result.Bytes)
   556  			}
   557  		},
   558  	}, {
   559  		desc:   "failure carried over to root",
   560  		failed: true,
   561  		output: "--- FAIL: root",
   562  		f:      func(b *B) { b.Fail() },
   563  	}, {
   564  		desc:   "skipping without message, chatty",
   565  		chatty: true,
   566  		output: "--- SKIP: root",
   567  		f:      func(b *B) { b.SkipNow() },
   568  	}, {
   569  		desc:   "chatty with recursion",
   570  		chatty: true,
   571  		f: func(b *B) {
   572  			b.Run("", func(b *B) {
   573  				b.Run("", func(b *B) {})
   574  			})
   575  		},
   576  	}, {
   577  		desc: "skipping without message, not chatty",
   578  		f:    func(b *B) { b.SkipNow() },
   579  	}, {
   580  		desc:   "skipping after error",
   581  		failed: true,
   582  		output: `
   583  --- FAIL: root
   584      sub_test.go:NNN: an error
   585      sub_test.go:NNN: skipped`,
   586  		f: func(b *B) {
   587  			b.Error("an error")
   588  			b.Skip("skipped")
   589  		},
   590  	}, {
   591  		desc: "memory allocation",
   592  		f: func(b *B) {
   593  			const bufSize = 256
   594  			alloc := func(b *B) {
   595  				var buf [bufSize]byte
   596  				for i := 0; i < b.N; i++ {
   597  					_ = append([]byte(nil), buf[:]...)
   598  				}
   599  			}
   600  			b.Run("", func(b *B) {
   601  				alloc(b)
   602  				b.ReportAllocs()
   603  			})
   604  			b.Run("", func(b *B) {
   605  				alloc(b)
   606  				b.ReportAllocs()
   607  			})
   608  			// runtime.MemStats sometimes reports more allocations than the
   609  			// benchmark is responsible for. Luckily the point of this test is
   610  			// to ensure that the results are not underreported, so we can
   611  			// simply verify the lower bound.
   612  			if got := b.result.MemAllocs; got < 2 {
   613  				t.Errorf("MemAllocs was %v; want 2", got)
   614  			}
   615  			if got := b.result.MemBytes; got < 2*bufSize {
   616  				t.Errorf("MemBytes was %v; want %v", got, 2*bufSize)
   617  			}
   618  		},
   619  	}, {
   620  		desc: "cleanup is called",
   621  		f: func(b *B) {
   622  			var calls, cleanups, innerCalls, innerCleanups int
   623  			b.Run("", func(b *B) {
   624  				calls++
   625  				b.Cleanup(func() {
   626  					cleanups++
   627  				})
   628  				b.Run("", func(b *B) {
   629  					b.Cleanup(func() {
   630  						innerCleanups++
   631  					})
   632  					innerCalls++
   633  				})
   634  				work(b)
   635  			})
   636  			if calls == 0 || calls != cleanups {
   637  				t.Errorf("mismatched cleanups; got %d want %d", cleanups, calls)
   638  			}
   639  			if innerCalls == 0 || innerCalls != innerCleanups {
   640  				t.Errorf("mismatched cleanups; got %d want %d", cleanups, calls)
   641  			}
   642  		},
   643  	}, {
   644  		desc:   "cleanup is called on failure",
   645  		failed: true,
   646  		f: func(b *B) {
   647  			var calls, cleanups int
   648  			b.Run("", func(b *B) {
   649  				calls++
   650  				b.Cleanup(func() {
   651  					cleanups++
   652  				})
   653  				b.Fatalf("failure")
   654  			})
   655  			if calls == 0 || calls != cleanups {
   656  				t.Errorf("mismatched cleanups; got %d want %d", cleanups, calls)
   657  			}
   658  		},
   659  	}}
   660  	hideStdoutForTesting = true
   661  	defer func() {
   662  		hideStdoutForTesting = false
   663  	}()
   664  	for _, tc := range testCases {
   665  		t.Run(tc.desc, func(t *T) {
   666  			var ok bool
   667  			buf := &strings.Builder{}
   668  			// This is almost like the Benchmark function, except that we override
   669  			// the benchtime and catch the failure result of the subbenchmark.
   670  			root := &B{
   671  				common: common{
   672  					signal: make(chan bool),
   673  					name:   "root",
   674  					w:      buf,
   675  				},
   676  				benchFunc: func(b *B) { ok = b.Run("test", tc.f) }, // Use Run to catch failure.
   677  				benchTime: durationOrCountFlag{d: 1 * time.Microsecond},
   678  			}
   679  			if tc.chatty {
   680  				root.chatty = newChattyPrinter(root.w)
   681  			}
   682  			root.runN(1)
   683  			if ok != !tc.failed {
   684  				t.Errorf("%s:ok: got %v; want %v", tc.desc, ok, !tc.failed)
   685  			}
   686  			if !ok != root.Failed() {
   687  				t.Errorf("%s:root failed: got %v; want %v", tc.desc, !ok, root.Failed())
   688  			}
   689  			// All tests are run as subtests
   690  			if root.result.N != 1 {
   691  				t.Errorf("%s: N for parent benchmark was %d; want 1", tc.desc, root.result.N)
   692  			}
   693  			got := strings.TrimSpace(buf.String())
   694  			want := strings.TrimSpace(tc.output)
   695  			re := makeRegexp(want)
   696  			if ok, err := regexp.MatchString(re, got); !ok || err != nil {
   697  				t.Errorf("%s:output:\ngot:\n%s\nwant:\n%s", tc.desc, got, want)
   698  			}
   699  		})
   700  	}
   701  }
   702  
   703  func makeRegexp(s string) string {
   704  	s = regexp.QuoteMeta(s)
   705  	s = strings.ReplaceAll(s, ":NNN:", `:\d\d\d\d?:`)
   706  	s = strings.ReplaceAll(s, "N\\.NNs", `\d*\.\d*s`)
   707  	return s
   708  }
   709  
   710  func TestBenchmarkOutput(t *T) {
   711  	// Ensure Benchmark initialized common.w by invoking it with an error and
   712  	// normal case.
   713  	Benchmark(func(b *B) { b.Error("do not print this output") })
   714  	Benchmark(func(b *B) {})
   715  }
   716  
   717  func TestBenchmarkStartsFrom1(t *T) {
   718  	var first = true
   719  	Benchmark(func(b *B) {
   720  		if first && b.N != 1 {
   721  			panic(fmt.Sprintf("Benchmark() first N=%v; want 1", b.N))
   722  		}
   723  		first = false
   724  	})
   725  }
   726  
   727  func TestBenchmarkReadMemStatsBeforeFirstRun(t *T) {
   728  	var first = true
   729  	Benchmark(func(b *B) {
   730  		if first && (b.startAllocs == 0 || b.startBytes == 0) {
   731  			panic("ReadMemStats not called before first run")
   732  		}
   733  		first = false
   734  	})
   735  }
   736  
   737  func TestParallelSub(t *T) {
   738  	c := make(chan int)
   739  	block := make(chan int)
   740  	for i := 0; i < 10; i++ {
   741  		go func(i int) {
   742  			<-block
   743  			t.Run(fmt.Sprint(i), func(t *T) {})
   744  			c <- 1
   745  		}(i)
   746  	}
   747  	close(block)
   748  	for i := 0; i < 10; i++ {
   749  		<-c
   750  	}
   751  }
   752  
   753  type funcWriter struct {
   754  	write func([]byte) (int, error)
   755  }
   756  
   757  func (fw *funcWriter) Write(b []byte) (int, error) {
   758  	return fw.write(b)
   759  }
   760  
   761  func TestRacyOutput(t *T) {
   762  	var runs int32  // The number of running Writes
   763  	var races int32 // Incremented for each race detected
   764  	raceDetector := func(b []byte) (int, error) {
   765  		// Check if some other goroutine is concurrently calling Write.
   766  		if atomic.LoadInt32(&runs) > 0 {
   767  			atomic.AddInt32(&races, 1) // Race detected!
   768  		}
   769  		atomic.AddInt32(&runs, 1)
   770  		defer atomic.AddInt32(&runs, -1)
   771  		runtime.Gosched() // Increase probability of a race
   772  		return len(b), nil
   773  	}
   774  
   775  	var wg sync.WaitGroup
   776  	root := &T{
   777  		common:  common{w: &funcWriter{raceDetector}},
   778  		context: newTestContext(1, allMatcher()),
   779  	}
   780  	root.chatty = newChattyPrinter(root.w)
   781  	root.Run("", func(t *T) {
   782  		for i := 0; i < 100; i++ {
   783  			wg.Add(1)
   784  			go func(i int) {
   785  				defer wg.Done()
   786  				t.Run(fmt.Sprint(i), func(t *T) {
   787  					t.Logf("testing run %d", i)
   788  				})
   789  			}(i)
   790  		}
   791  	})
   792  	wg.Wait()
   793  
   794  	if races > 0 {
   795  		t.Errorf("detected %d racy Writes", races)
   796  	}
   797  }
   798  
   799  // The late log message did not include the test name.  Issue 29388.
   800  func TestLogAfterComplete(t *T) {
   801  	ctx := newTestContext(1, allMatcher())
   802  	var buf bytes.Buffer
   803  	t1 := &T{
   804  		common: common{
   805  			// Use a buffered channel so that tRunner can write
   806  			// to it although nothing is reading from it.
   807  			signal: make(chan bool, 1),
   808  			w:      &buf,
   809  		},
   810  		context: ctx,
   811  	}
   812  
   813  	c1 := make(chan bool)
   814  	c2 := make(chan string)
   815  	tRunner(t1, func(t *T) {
   816  		t.Run("TestLateLog", func(t *T) {
   817  			go func() {
   818  				defer close(c2)
   819  				defer func() {
   820  					p := recover()
   821  					if p == nil {
   822  						c2 <- "subtest did not panic"
   823  						return
   824  					}
   825  					s, ok := p.(string)
   826  					if !ok {
   827  						c2 <- fmt.Sprintf("subtest panic with unexpected value %v", p)
   828  						return
   829  					}
   830  					const want = "Log in goroutine after TestLateLog has completed: log after test"
   831  					if !strings.Contains(s, want) {
   832  						c2 <- fmt.Sprintf("subtest panic %q does not contain %q", s, want)
   833  					}
   834  				}()
   835  
   836  				<-c1
   837  				t.Log("log after test")
   838  			}()
   839  		})
   840  	})
   841  	close(c1)
   842  
   843  	if s := <-c2; s != "" {
   844  		t.Error(s)
   845  	}
   846  }
   847  
   848  func TestBenchmark(t *T) {
   849  	if Short() {
   850  		t.Skip("skipping in short mode")
   851  	}
   852  	res := Benchmark(func(b *B) {
   853  		for i := 0; i < 5; i++ {
   854  			b.Run("", func(b *B) {
   855  				for i := 0; i < b.N; i++ {
   856  					time.Sleep(time.Millisecond)
   857  				}
   858  			})
   859  		}
   860  	})
   861  	if res.NsPerOp() < 4000000 {
   862  		t.Errorf("want >5ms; got %v", time.Duration(res.NsPerOp()))
   863  	}
   864  }
   865  
   866  func TestCleanup(t *T) {
   867  	var cleanups []int
   868  	t.Run("test", func(t *T) {
   869  		t.Cleanup(func() { cleanups = append(cleanups, 1) })
   870  		t.Cleanup(func() { cleanups = append(cleanups, 2) })
   871  	})
   872  	if got, want := cleanups, []int{2, 1}; !reflect.DeepEqual(got, want) {
   873  		t.Errorf("unexpected cleanup record; got %v want %v", got, want)
   874  	}
   875  }
   876  
   877  func TestConcurrentCleanup(t *T) {
   878  	cleanups := 0
   879  	t.Run("test", func(t *T) {
   880  		done := make(chan struct{})
   881  		for i := 0; i < 2; i++ {
   882  			i := i
   883  			go func() {
   884  				t.Cleanup(func() {
   885  					cleanups |= 1 << i
   886  				})
   887  				done <- struct{}{}
   888  			}()
   889  		}
   890  		<-done
   891  		<-done
   892  	})
   893  	if cleanups != 1|2 {
   894  		t.Errorf("unexpected cleanup; got %d want 3", cleanups)
   895  	}
   896  }
   897  
   898  func TestCleanupCalledEvenAfterGoexit(t *T) {
   899  	cleanups := 0
   900  	t.Run("test", func(t *T) {
   901  		t.Cleanup(func() {
   902  			cleanups++
   903  		})
   904  		t.Cleanup(func() {
   905  			runtime.Goexit()
   906  		})
   907  	})
   908  	if cleanups != 1 {
   909  		t.Errorf("unexpected cleanup count; got %d want 1", cleanups)
   910  	}
   911  }
   912  
   913  func TestRunCleanup(t *T) {
   914  	outerCleanup := 0
   915  	innerCleanup := 0
   916  	t.Run("test", func(t *T) {
   917  		t.Cleanup(func() { outerCleanup++ })
   918  		t.Run("x", func(t *T) {
   919  			t.Cleanup(func() { innerCleanup++ })
   920  		})
   921  	})
   922  	if innerCleanup != 1 {
   923  		t.Errorf("unexpected inner cleanup count; got %d want 1", innerCleanup)
   924  	}
   925  	if outerCleanup != 1 {
   926  		t.Errorf("unexpected outer cleanup count; got %d want 0", outerCleanup)
   927  	}
   928  }
   929  
   930  func TestCleanupParallelSubtests(t *T) {
   931  	ranCleanup := 0
   932  	t.Run("test", func(t *T) {
   933  		t.Cleanup(func() { ranCleanup++ })
   934  		t.Run("x", func(t *T) {
   935  			t.Parallel()
   936  			if ranCleanup > 0 {
   937  				t.Error("outer cleanup ran before parallel subtest")
   938  			}
   939  		})
   940  	})
   941  	if ranCleanup != 1 {
   942  		t.Errorf("unexpected cleanup count; got %d want 1", ranCleanup)
   943  	}
   944  }
   945  
   946  func TestNestedCleanup(t *T) {
   947  	ranCleanup := 0
   948  	t.Run("test", func(t *T) {
   949  		t.Cleanup(func() {
   950  			if ranCleanup != 2 {
   951  				t.Errorf("unexpected cleanup count in first cleanup: got %d want 2", ranCleanup)
   952  			}
   953  			ranCleanup++
   954  		})
   955  		t.Cleanup(func() {
   956  			if ranCleanup != 0 {
   957  				t.Errorf("unexpected cleanup count in second cleanup: got %d want 0", ranCleanup)
   958  			}
   959  			ranCleanup++
   960  			t.Cleanup(func() {
   961  				if ranCleanup != 1 {
   962  					t.Errorf("unexpected cleanup count in nested cleanup: got %d want 1", ranCleanup)
   963  				}
   964  				ranCleanup++
   965  			})
   966  		})
   967  	})
   968  	if ranCleanup != 3 {
   969  		t.Errorf("unexpected cleanup count: got %d want 3", ranCleanup)
   970  	}
   971  }