github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/tests/process.go (about)

     1  package tests
     2  
     3  import (
     4  	"io"
     5  	"io/ioutil"
     6  	"os"
     7  	"os/exec"
     8  	"time"
     9  )
    10  
    11  // execution process
    12  type Process struct {
    13  	ExecPath   string
    14  	Args       []string
    15  	Pid        int
    16  	StartTime  time.Time
    17  	EndTime    time.Time
    18  	Cmd        *exec.Cmd        `json:"-"`
    19  	ExitState  *os.ProcessState `json:"-"`
    20  	StdinPipe  io.WriteCloser   `json:"-"`
    21  	StdoutPipe io.ReadCloser    `json:"-"`
    22  	StderrPipe io.ReadCloser    `json:"-"`
    23  }
    24  
    25  // dir: The working directory. If "", os.Getwd() is used.
    26  // name: Command name
    27  // args: Args to command. (should not include name)
    28  func StartProcess(dir string, name string, args []string) (*Process, error) {
    29  	proc, err := CreateProcess(dir, name, args)
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  	// cmd start
    34  	if err := proc.Cmd.Start(); err != nil {
    35  		return nil, err
    36  	}
    37  	proc.Pid = proc.Cmd.Process.Pid
    38  
    39  	return proc, nil
    40  }
    41  
    42  // Same as StartProcess but doesn't start the process
    43  func CreateProcess(dir string, name string, args []string) (*Process, error) {
    44  	var cmd = exec.Command(name, args...) // is not yet started.
    45  	// cmd dir
    46  	if dir == "" {
    47  		pwd, err := os.Getwd()
    48  		if err != nil {
    49  			panic(err)
    50  		}
    51  		cmd.Dir = pwd
    52  	} else {
    53  		cmd.Dir = dir
    54  	}
    55  	// cmd stdin
    56  	stdin, err := cmd.StdinPipe()
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	stdout, err := cmd.StdoutPipe()
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	stderr, err := cmd.StderrPipe()
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	proc := &Process{
    72  		ExecPath:   name,
    73  		Args:       args,
    74  		StartTime:  time.Now(),
    75  		Cmd:        cmd,
    76  		ExitState:  nil,
    77  		StdinPipe:  stdin,
    78  		StdoutPipe: stdout,
    79  		StderrPipe: stderr,
    80  	}
    81  	return proc, nil
    82  }
    83  
    84  // stop the process
    85  func (proc *Process) Stop(kill bool) error {
    86  	if kill {
    87  		// fmt.Printf("Killing process %v\n", proc.Cmd.Process)
    88  		return proc.Cmd.Process.Kill()
    89  	}
    90  	return proc.Cmd.Process.Signal(os.Interrupt)
    91  }
    92  
    93  // wait for the process
    94  func (proc *Process) Wait() {
    95  	err := proc.Cmd.Wait()
    96  	if err != nil {
    97  		// fmt.Printf("Process exit: %v\n", err)
    98  		if exitError, ok := err.(*exec.ExitError); ok {
    99  			proc.ExitState = exitError.ProcessState
   100  		}
   101  	}
   102  	proc.ExitState = proc.Cmd.ProcessState
   103  	proc.EndTime = time.Now() // TODO make this goroutine-safe
   104  }
   105  
   106  // ReadAll calls ioutil.ReadAll on the StdoutPipe and StderrPipe.
   107  func (proc *Process) ReadAll() (stdout []byte, stderr []byte, err error) {
   108  	outbz, err := ioutil.ReadAll(proc.StdoutPipe)
   109  	if err != nil {
   110  		return nil, nil, err
   111  	}
   112  	errbz, err := ioutil.ReadAll(proc.StderrPipe)
   113  	if err != nil {
   114  		return nil, nil, err
   115  	}
   116  	return outbz, errbz, nil
   117  }