github.com/sdboyer/gps@v0.16.3/cmd_test.go (about)

     1  package gps
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"os/exec"
     8  	"testing"
     9  	"time"
    10  )
    11  
    12  func mkTestCmd(iterations int) *monitoredCmd {
    13  	return newMonitoredCmd(
    14  		exec.Command("./echosleep", "-n", fmt.Sprint(iterations)),
    15  		500*time.Millisecond,
    16  	)
    17  }
    18  
    19  func TestMonitoredCmd(t *testing.T) {
    20  	// Sleeps and compile make this a bit slow
    21  	if testing.Short() {
    22  		t.Skip("skipping test with sleeps on short")
    23  	}
    24  
    25  	err := exec.Command("go", "build", "./_testdata/cmd/echosleep.go").Run()
    26  	if err != nil {
    27  		t.Errorf("Unable to build echosleep binary: %s", err)
    28  	}
    29  	defer os.Remove("./echosleep")
    30  
    31  	cmd := mkTestCmd(2)
    32  	err = cmd.run(context.Background())
    33  	if err != nil {
    34  		t.Errorf("Expected command not to fail: %s", err)
    35  	}
    36  
    37  	expectedOutput := "foo\nfoo\n"
    38  	if cmd.stdout.buf.String() != expectedOutput {
    39  		t.Errorf("Unexpected output:\n\t(GOT): %s\n\t(WNT): %s", cmd.stdout.buf.String(), expectedOutput)
    40  	}
    41  
    42  	cmd2 := mkTestCmd(10)
    43  	err = cmd2.run(context.Background())
    44  	if err == nil {
    45  		t.Error("Expected command to fail")
    46  	}
    47  
    48  	_, ok := err.(*timeoutError)
    49  	if !ok {
    50  		t.Errorf("Expected a timeout error, but got: %s", err)
    51  	}
    52  
    53  	expectedOutput = "foo\nfoo\nfoo\nfoo\n"
    54  	if cmd2.stdout.buf.String() != expectedOutput {
    55  		t.Errorf("Unexpected output:\n\t(GOT): %s\n\t(WNT): %s", cmd2.stdout.buf.String(), expectedOutput)
    56  	}
    57  
    58  	ctx, cancel := context.WithCancel(context.Background())
    59  	sync1, errchan := make(chan struct{}), make(chan error)
    60  	cmd3 := mkTestCmd(2)
    61  	go func() {
    62  		close(sync1)
    63  		errchan <- cmd3.run(ctx)
    64  	}()
    65  
    66  	// Make sure goroutine is at least started before we cancel the context.
    67  	<-sync1
    68  	// Give it a bit to get the process started.
    69  	<-time.After(5 * time.Millisecond)
    70  	cancel()
    71  
    72  	err = <-errchan
    73  	if err != context.Canceled {
    74  		t.Errorf("should have gotten canceled error, got %s", err)
    75  	}
    76  }