3434	flagSkipRegexp  string 
3535	flagShuffle     string 
3636	flagCount       int 
37+ 	flagTimeout     time.Duration 
3738)
3839
3940var  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. 
518518func  (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
549551type  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