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