Skip to content

Commit 1dcbb85

Browse files
committed
testing: implement the -timeout flag
1 parent 8b7fc17 commit 1dcbb85

File tree

3 files changed

+36
-6
lines changed

3 files changed

+36
-6
lines changed

compileopts/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"regexp"
1111
"strconv"
1212
"strings"
13+
"time"
1314

1415
"github.com/google/shlex"
1516
"github.com/tinygo-org/tinygo/goenv"
@@ -659,4 +660,5 @@ type TestConfig struct {
659660
BenchTime string
660661
BenchMem bool
661662
Shuffle string
663+
Timeout time.Duration
662664
}

main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ func Test(pkgName string, stdout, stderr io.Writer, options *compileopts.Options
238238
if testConfig.Shuffle != "" {
239239
flags = append(flags, "-test.shuffle="+testConfig.Shuffle)
240240
}
241+
if t := testConfig.Timeout; t != 0 {
242+
flags = append(flags, "-test.timeout="+t.String())
243+
}
241244

242245
logToStdout := testConfig.Verbose || testConfig.BenchRegexp != ""
243246

@@ -1675,6 +1678,7 @@ func main() {
16751678
flag.StringVar(&testConfig.BenchTime, "benchtime", "", "run each benchmark for duration `d`")
16761679
flag.BoolVar(&testConfig.BenchMem, "benchmem", false, "show memory stats for benchmarks")
16771680
flag.StringVar(&testConfig.Shuffle, "shuffle", "", "shuffle the order the tests and benchmarks run")
1681+
flag.DurationVar(&testConfig.Timeout, "timeout", 10*time.Minute, "panic test binary after duration `d`")
16781682
}
16791683

16801684
// Early command processing, before commands are interpreted by the Go flag

src/testing/testing.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ var (
3434
flagSkipRegexp string
3535
flagShuffle string
3636
flagCount int
37+
flagTimeout time.Duration
3738
)
3839

3940
var initRan bool
@@ -52,6 +53,7 @@ func Init() {
5253
flag.StringVar(&flagShuffle, "test.shuffle", "off", "shuffle: off, on, <numeric-seed>")
5354

5455
flag.IntVar(&flagCount, "test.count", 1, "run each test or benchmark `count` times")
56+
flag.DurationVar(&flagTimeout, "test.timeout", 0, "panic test binary after duration d (default 0, timeout disabled)")
5557

5658
initBenchmarkFlags()
5759
}
@@ -513,8 +515,6 @@ func (t *T) Run(name string, f func(t *T)) bool {
513515
//
514516
// The ok result is false if the -timeout flag indicates “no timeout” (0).
515517
// For now tinygo always return 0, false.
516-
//
517-
// Not Implemented.
518518
func (t *T) Deadline() (deadline time.Time, ok bool) {
519519
deadline = t.context.deadline
520520
return deadline, !deadline.IsZero()
@@ -527,7 +527,7 @@ type testContext struct {
527527
deadline time.Time
528528
}
529529

530-
func newTestContext(m *matcher) *testContext {
530+
func newTestContext(deadline time.Time, m *matcher) *testContext {
531531
return &testContext{
532532
match: m,
533533
}
@@ -544,6 +544,8 @@ type M struct {
544544
// value to pass to os.Exit, the outer test func main
545545
// harness calls os.Exit with this code. See #34129.
546546
exitCode int
547+
548+
timer *time.Timer
547549
}
548550

549551
type testDeps interface {
@@ -588,7 +590,8 @@ func (m *M) Run() (code int) {
588590
}
589591
}
590592

591-
testRan, testOk := runTests(m.deps.MatchString, m.Tests)
593+
deadline := m.startAlarm()
594+
testRan, testOk := runTests(deadline, m.deps.MatchString, m.Tests)
592595
if !testRan && *matchBenchmarks == "" {
593596
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
594597
}
@@ -599,13 +602,34 @@ func (m *M) Run() (code int) {
599602
fmt.Println("PASS")
600603
m.exitCode = 0
601604
}
605+
m.stopAlarm()
602606
return
603607
}
604608

605-
func runTests(matchString func(pat, str string) (bool, error), tests []InternalTest) (ran, ok bool) {
609+
// startAlarm starts an alarm if requested.
610+
func (m *M) startAlarm() time.Time {
611+
if flagTimeout <= 0 {
612+
return time.Time{}
613+
}
614+
615+
deadline := time.Now().Add(flagTimeout)
616+
m.timer = time.AfterFunc(flagTimeout, func() {
617+
panic(fmt.Sprintf("test timed out after %v", flagTimeout))
618+
})
619+
return deadline
620+
}
621+
622+
// stopAlarm turns off the alarm.
623+
func (m *M) stopAlarm() {
624+
if flagTimeout > 0 {
625+
m.timer.Stop()
626+
}
627+
}
628+
629+
func runTests(deadline time.Time, matchString func(pat, str string) (bool, error), tests []InternalTest) (ran, ok bool) {
606630
ok = true
607631

608-
ctx := newTestContext(newMatcher(matchString, flagRunRegexp, "-test.run", flagSkipRegexp))
632+
ctx := newTestContext(deadline, newMatcher(matchString, flagRunRegexp, "-test.run", flagSkipRegexp))
609633
t := &T{
610634
common: common{
611635
output: &logger{logToStdout: flagVerbose},

0 commit comments

Comments
 (0)