func (c *Cmd) StderrMatches(regex string) bool {
	c.t.Helper()
	c.validateHasStarted()
	re := regexp.MustCompile(regex)
	return retryStringTest(func(got, want string) bool {
		return re.MatchString(got)
	}, c.stderr, regex)
}
StderrMatches compares a regex to the stderr produced by the command.
package testcli
import (
	"bufio"
	"bytes"
	"errors"
	"io"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"sync"
	"testing"
	"time"
)
type output struct {
	content string
	mu      *sync.Mutex
}
type Cmd struct {
	cmd       *exec.Cmd
	env       []string
	exitError error
	status    string
	stdout    *output
	stderr    *output
	stdin     io.Reader
	t         *testing.T
}
var ErrUninitializedCmd = errors.New("You need to run this command first")
var ErrCmdNotFinished = errors.New("Command is still executing")
const (
	initialized = "initialized"
	running = "running"
	finished = "finished"
)
var pkgCmd *Cmd
func Command(t *testing.T, name string, arg ...string) *Cmd {
	return &Cmd{
		cmd:    exec.Command(name, arg...),
		t:      t,
		status: initialized,
		stdout: &output{mu: &sync.Mutex{}},
		stderr: &output{mu: &sync.Mutex{}},
	}
}
func (c *Cmd) validateIsFinished() {
	c.t.Helper()
	if c.status != finished {
		c.t.Fatal(ErrCmdNotFinished)
	}
}
func (c *Cmd) validateHasStarted() {
	c.t.Helper()
	if !(c.status == running || c.status == finished) {
		c.t.Fatal(ErrUninitializedCmd)
	}
}
func (c *Cmd) SetEnv(env []string) {
	c.env = env
}
func (c *Cmd) SetStdin(stdin io.Reader) {
	c.stdin = stdin
}
func (c *Cmd) Run() {
	c.t.Helper()
	if c.stdin != nil {
		c.cmd.Stdin = c.stdin
	}
	if c.env != nil {
		c.cmd.Env = c.env
	} else {
		c.cmd.Env = os.Environ()
	}
	var outBuf bytes.Buffer
	c.cmd.Stdout = &outBuf
	var errBuf bytes.Buffer
	c.cmd.Stderr = &errBuf
	if err := c.cmd.Run(); err != nil {
		c.exitError = err
	}
	c.stdout.content = string(outBuf.Bytes())
	c.stderr.content = string(errBuf.Bytes())
	c.status = finished
}
func (c *Cmd) Start() {
	c.t.Helper()
	if c.stdin != nil {
		c.cmd.Stdin = c.stdin
	}
	if c.env != nil {
		c.cmd.Env = c.env
	} else {
		c.cmd.Env = os.Environ()
	}
	stdoutPipe, err := c.cmd.StdoutPipe()
	if err != nil {
		c.t.Fatal(err)
	}
	stderrPipe, err := c.cmd.StderrPipe()
	if err != nil {
		c.t.Fatal(err)
	}
	if err := c.cmd.Start(); err != nil {
		c.exitError = err
	}
	go func() {
		scanner := bufio.NewScanner(stdoutPipe)
		for scanner.Scan() {
			c.stdout.mu.Lock()
			c.stdout.content += scanner.Text() + "\n"
			c.stdout.mu.Unlock()
		}
		if err := scanner.Err(); err != nil {
			c.t.Fatal(err)
		}
	}()
	go func() {
		scanner := bufio.NewScanner(stderrPipe)
		for scanner.Scan() {
			c.stderr.mu.Lock()
			c.stderr.content += scanner.Text() + "\n"
			c.stderr.mu.Unlock()
		}
		if err := scanner.Err(); err != nil {
			c.t.Fatal(err)
		}
	}()
	c.status = running
}
func (c *Cmd) Wait() {
	c.t.Helper()
	c.validateHasStarted()
	if err := c.cmd.Wait(); err != nil {
		c.exitError = err
	}
	c.status = finished
}
func (c *Cmd) Kill() {
	c.t.Helper()
	c.validateHasStarted()
	err := c.cmd.Process.Kill()
	if err != nil {
		c.t.Fatal(err)
	}
	c.status = finished
}
func Run(t *testing.T, name string, arg ...string) {
	t.Helper()
	pkgCmd = Command(t, name, arg...)
	pkgCmd.Run()
}
func (c *Cmd) Error() error {
	c.t.Helper()
	c.validateIsFinished()
	return c.exitError
}
func Error() error {
	pkgCmd.t.Helper()
	return pkgCmd.Error()
}
func (c *Cmd) Stdout() string {
	c.t.Helper()
	c.validateHasStarted()
	c.stdout.mu.Lock()
	defer c.stdout.mu.Unlock()
	return c.stdout.content
}
func Stdout() string {
	pkgCmd.t.Helper()
	return pkgCmd.Stdout()
}
func (c *Cmd) Stderr() string {
	c.t.Helper()
	c.validateHasStarted()
	c.stderr.mu.Lock()
	defer c.stderr.mu.Unlock()
	return c.stderr.content
}
func Stderr() string {
	pkgCmd.t.Helper()
	return pkgCmd.Stderr()
}
func (c *Cmd) StdoutContains(str string) bool {
	c.t.Helper()
	c.validateHasStarted()
	str = strings.ToLower(str)
	return retryStringTest(strings.Contains, c.stdout, str)
}
func StdoutContains(str string) bool {
	pkgCmd.t.Helper()
	return pkgCmd.StdoutContains(str)
}
func (c *Cmd) StderrContains(str string) bool {
	c.t.Helper()
	c.validateHasStarted()
	str = strings.ToLower(str)
	return retryStringTest(strings.Contains, c.stderr, str)
}
func StderrContains(str string) bool {
	pkgCmd.t.Helper()
	return pkgCmd.StderrContains(str)
}
func (c *Cmd) Success() bool {
	c.t.Helper()
	c.validateIsFinished()
	return c.exitError == nil
}
func Success() bool {
	pkgCmd.t.Helper()
	return pkgCmd.Success()
}
func (c *Cmd) Failure() bool {
	c.t.Helper()
	c.validateIsFinished()
	return c.exitError != nil
}
func Failure() bool {
	pkgCmd.t.Helper()
	return pkgCmd.Failure()
}
func (c *Cmd) StdoutMatches(regex string) bool {
	c.t.Helper()
	c.validateHasStarted()
	re := regexp.MustCompile(regex)
	return retryStringTest(func(got, want string) bool {
		return re.MatchString(got)
	}, c.stdout, regex)
}
func StdoutMatches(regex string) bool {
	pkgCmd.t.Helper()
	return pkgCmd.StdoutMatches(regex)
}