@@ -234,14 +234,20 @@ func (ts *TestScript) cmdEnv(neg bool, args []string) {
234234 }
235235}
236236
237+ var backgroundSpecifier = regexp .MustCompile (`^&([a-zA-Z_0-9]+&)?$` )
238+
237239// exec runs the given command.
238240func (ts * TestScript ) cmdExec (neg bool , args []string ) {
239241 if len (args ) < 1 || (len (args ) == 1 && args [0 ] == "&" ) {
240242 ts .Fatalf ("usage: exec program [args...] [&]" )
241243 }
242244
243245 var err error
244- if len (args ) > 0 && args [len (args )- 1 ] == "&" {
246+ if len (args ) > 0 && backgroundSpecifier .MatchString (args [len (args )- 1 ]) {
247+ bgName := strings .TrimSuffix (strings .TrimPrefix (args [len (args )- 1 ], "&" ), "&" )
248+ if ts .findBackground (bgName ) != nil {
249+ ts .Fatalf ("duplicate background process name %q" , bgName )
250+ }
245251 var cmd * exec.Cmd
246252 cmd , err = ts .execBackground (args [0 ], args [1 :len (args )- 1 ]... )
247253 if err == nil {
@@ -250,7 +256,7 @@ func (ts *TestScript) cmdExec(neg bool, args []string) {
250256 ctxWait (ts .ctxt , cmd )
251257 close (wait )
252258 }()
253- ts .background = append (ts .background , backgroundCmd {cmd , wait , neg })
259+ ts .background = append (ts .background , backgroundCmd {bgName , cmd , wait , neg })
254260 }
255261 ts .stdout , ts .stderr = "" , ""
256262 } else {
@@ -449,16 +455,69 @@ func (ts *TestScript) cmdUNIX2DOS(neg bool, args []string) {
449455
450456// Tait waits for background commands to exit, setting stderr and stdout to their result.
451457func (ts * TestScript ) cmdWait (neg bool , args []string ) {
458+ if len (args ) > 1 {
459+ ts .Fatalf ("usage: wait [name]" )
460+ }
452461 if neg {
453462 ts .Fatalf ("unsupported: ! wait" )
454463 }
455464 if len (args ) > 0 {
456- ts .Fatalf ("usage: wait" )
465+ ts .waitBackgroundOne (args [0 ])
466+ } else {
467+ ts .waitBackground (true )
468+ }
469+ }
470+
471+ func (ts * TestScript ) waitBackgroundOne (bgName string ) {
472+ bg := ts .findBackground (bgName )
473+ if bg == nil {
474+ ts .Fatalf ("unknown background process %q" , bgName )
475+ }
476+ <- bg .wait
477+ ts .stdout = bg .cmd .Stdout .(* strings.Builder ).String ()
478+ ts .stderr = bg .cmd .Stderr .(* strings.Builder ).String ()
479+ if ts .stdout != "" {
480+ fmt .Fprintf (& ts .log , "[stdout]\n %s" , ts .stdout )
481+ }
482+ if ts .stderr != "" {
483+ fmt .Fprintf (& ts .log , "[stderr]\n %s" , ts .stderr )
484+ }
485+ // Note: ignore bg.neg, which only takes effect on the non-specific
486+ // wait command.
487+ if bg .cmd .ProcessState .Success () {
488+ if bg .neg {
489+ ts .Fatalf ("unexpected command success" )
490+ }
491+ } else {
492+ if ts .ctxt .Err () != nil {
493+ ts .Fatalf ("test timed out while running command" )
494+ } else if ! bg .neg {
495+ ts .Fatalf ("unexpected command failure" )
496+ }
497+ }
498+ // Remove this process from the list of running background processes.
499+ for i := range ts .background {
500+ if bg == & ts .background [i ] {
501+ ts .background = append (ts .background [:i ], ts .background [i + 1 :]... )
502+ break
503+ }
504+ }
505+ }
506+
507+ func (ts * TestScript ) findBackground (bgName string ) * backgroundCmd {
508+ if bgName == "" {
509+ return nil
510+ }
511+ for i := range ts .background {
512+ bg := & ts .background [i ]
513+ if bg .name == bgName {
514+ return bg
515+ }
457516 }
458- ts . waitBackground ( true , neg )
517+ return nil
459518}
460519
461- func (ts * TestScript ) waitBackground (checkStatus bool , neg bool ) {
520+ func (ts * TestScript ) waitBackground (checkStatus bool ) {
462521 var stdouts , stderrs []string
463522 for _ , bg := range ts .background {
464523 <- bg .wait
0 commit comments