mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-25 12:27:43 +08:00
This is intended as a replacement for sharness. These are vanilla Go tests which can be run in your IDE for quick iteration on end-to-end CLI tests. This also removes IPTB by duplicating its functionality in the test harness. This isn't a big deal...IPTB's complexity is mostly around the fact that its state needs to be saved to disk in between `iptb` command invocations, and that it uses Go plugins to inject functionality, neither of which are relevant here. If we merge this, we'll have to live with bifurcated tests for a while until they are all migrated. I'd recommend we self-enforce a rule that, if we need to touch a sharness test, we migrate it and one more test over to Go tests first. Then eventually we will have migrated everything.
141 lines
2.8 KiB
Go
141 lines
2.8 KiB
Go
package harness
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"os/exec"
|
|
"strings"
|
|
)
|
|
|
|
// Runner is a process runner which can run subprocesses and aggregate output.
|
|
type Runner struct {
|
|
Env map[string]string
|
|
Dir string
|
|
Verbose bool
|
|
}
|
|
|
|
type CmdOpt func(*exec.Cmd)
|
|
type RunFunc func(*exec.Cmd) error
|
|
|
|
var RunFuncStart = (*exec.Cmd).Start
|
|
|
|
type RunRequest struct {
|
|
Path string
|
|
Args []string
|
|
// Options that are applied to the exec.Cmd just before running it
|
|
CmdOpts []CmdOpt
|
|
// Function to use to run the command.
|
|
// If not specified, defaults to cmd.Run
|
|
RunFunc func(*exec.Cmd) error
|
|
Verbose bool
|
|
}
|
|
|
|
type RunResult struct {
|
|
Stdout *Buffer
|
|
Stderr *Buffer
|
|
Err error
|
|
ExitErr *exec.ExitError
|
|
Cmd *exec.Cmd
|
|
}
|
|
|
|
func environToMap(environ []string) map[string]string {
|
|
m := map[string]string{}
|
|
for _, e := range environ {
|
|
kv := strings.Split(e, "=")
|
|
m[kv[0]] = kv[1]
|
|
}
|
|
return m
|
|
}
|
|
|
|
func (r *Runner) Run(req RunRequest) RunResult {
|
|
cmd := exec.Command(req.Path, req.Args...)
|
|
stdout := &Buffer{}
|
|
stderr := &Buffer{}
|
|
cmd.Stdout = stdout
|
|
cmd.Stderr = stderr
|
|
cmd.Dir = r.Dir
|
|
|
|
for k, v := range r.Env {
|
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, v))
|
|
}
|
|
|
|
for _, o := range req.CmdOpts {
|
|
o(cmd)
|
|
}
|
|
|
|
if req.RunFunc == nil {
|
|
req.RunFunc = (*exec.Cmd).Run
|
|
}
|
|
|
|
log.Debugf("running %v", cmd.Args)
|
|
|
|
err := req.RunFunc(cmd)
|
|
|
|
result := RunResult{
|
|
Stdout: stdout,
|
|
Stderr: stderr,
|
|
Cmd: cmd,
|
|
Err: err,
|
|
}
|
|
|
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
|
result.ExitErr = exitErr
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// MustRun runs the command and fails the test if the command fails.
|
|
func (r *Runner) MustRun(req RunRequest) RunResult {
|
|
result := r.Run(req)
|
|
r.AssertNoError(result)
|
|
return result
|
|
}
|
|
|
|
func (r *Runner) AssertNoError(result RunResult) {
|
|
if result.ExitErr != nil {
|
|
log.Panicf("'%s' returned error, code: %d, err: %s\nstdout:%s\nstderr:%s\n",
|
|
result.Cmd.Args, result.ExitErr.ExitCode(), result.ExitErr.Error(), result.Stdout.String(), result.Stderr.String())
|
|
|
|
}
|
|
if result.Err != nil {
|
|
log.Panicf("unable to run %s: %s", result.Cmd.Path, result.Err)
|
|
|
|
}
|
|
}
|
|
|
|
func RunWithEnv(env map[string]string) CmdOpt {
|
|
return func(cmd *exec.Cmd) {
|
|
for k, v := range env {
|
|
cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, v))
|
|
}
|
|
}
|
|
}
|
|
|
|
func RunWithPath(path string) CmdOpt {
|
|
return func(cmd *exec.Cmd) {
|
|
var newEnv []string
|
|
for _, env := range cmd.Env {
|
|
e := strings.Split(env, "=")
|
|
if e[0] == "PATH" {
|
|
paths := strings.Split(e[1], ":")
|
|
paths = append(paths, path)
|
|
e[1] = strings.Join(paths, ":")
|
|
fmt.Printf("path: %s\n", strings.Join(e, "="))
|
|
}
|
|
newEnv = append(newEnv, strings.Join(e, "="))
|
|
}
|
|
cmd.Env = newEnv
|
|
}
|
|
}
|
|
|
|
func RunWithStdin(reader io.Reader) CmdOpt {
|
|
return func(cmd *exec.Cmd) {
|
|
cmd.Stdin = reader
|
|
}
|
|
}
|
|
|
|
func RunWithStdinStr(s string) CmdOpt {
|
|
return RunWithStdin(strings.NewReader(s))
|
|
}
|