Files
kopia/cli/inproc.go
Jarek Kowalski 8515d050e5 test(infra): improved support for in-process testing (#2169)
* feat(infra): improved support for in-process testing

* support for killing of a running server using simulated Ctrl-C
* support for overriding os.Stdin
* migrated many tests from the exe runner to in-process runner

* added required indirection when defining Envar() so we can later override it in tests

* refactored CLI runners by moving environment overrides to CLITestEnv
2022-07-09 18:22:50 -07:00

67 lines
1.5 KiB
Go

package cli
import (
"context"
"io"
"github.com/alecthomas/kingpin"
"github.com/pkg/errors"
"github.com/kopia/kopia/internal/releasable"
"github.com/kopia/kopia/repo/logging"
)
// RunSubcommand executes the subcommand asynchronously in current process
// with flags in an isolated CLI environment and returns standard output and standard error.
func (c *App) RunSubcommand(ctx context.Context, kpapp *kingpin.Application, stdin io.Reader, argsAndFlags []string) (stdout, stderr io.Reader, wait func() error, kill func()) {
stdoutReader, stdoutWriter := io.Pipe()
stderrReader, stderrWriter := io.Pipe()
c.stdinReader = stdin
c.stdoutWriter = stdoutWriter
c.stderrWriter = stderrWriter
c.rootctx = logging.WithLogger(ctx, logging.ToWriter(stderrWriter))
c.simulatedCtrlC = make(chan bool, 1)
releasable.Created("simulated-ctrl-c", c.simulatedCtrlC)
c.Attach(kpapp)
var exitCode int
resultErr := make(chan error, 1)
c.osExit = func(ec int) {
exitCode = ec
}
go func() {
defer func() {
close(c.simulatedCtrlC)
releasable.Released("simulated-ctrl-c", c.simulatedCtrlC)
}()
defer close(resultErr)
defer stderrWriter.Close() //nolint:errcheck
defer stdoutWriter.Close() //nolint:errcheck
_, err := kpapp.Parse(argsAndFlags)
if err != nil {
resultErr <- err
return
}
if exitCode != 0 {
resultErr <- errors.Errorf("exit code %v", exitCode)
return
}
}()
return stdoutReader, stderrReader, func() error {
return <-resultErr
}, func() {
// deliver simulated Ctrl-C to the app.
c.simulatedCtrlC <- true
}
}