goc/tests/e2e/cmd.go
2021-09-09 14:26:42 +08:00

142 lines
3.3 KiB
Go

/*
Copyright 2021 Qiniu Cloud (qiniu.com)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package e2e
import (
"bytes"
"context"
"fmt"
"os"
"os/exec"
"runtime"
"strings"
"sync"
"time"
)
// LongRunCmd defines a cmd which run for a long time
type LongRunCmd struct {
cancel context.CancelFunc
cmd *exec.Cmd
stderrBuf bytes.Buffer
stdoutBuf bytes.Buffer
err error
done bool
once sync.Once
}
// NewLongRunCmd defines a command which will be run forever
//
// You can specify the whole command arg list, the directory where the command
// will be run in, and the env list.
//
// args 命令列表
//
// dir 命令运行所在的目录
//
// envs 额外的环境变量
func NewLongRunCmd(args []string, dir string, envs []string) *LongRunCmd {
ctx, cancel := context.WithCancel(context.Background())
cmd := exec.CommandContext(ctx, args[0], args[1:]...)
if runtime.GOOS == "windows" {
cmd = exec.CommandContext(ctx, args[0]+".exe", args[1:]...)
}
cmd.Dir = dir
cmd.Env = append(os.Environ(), envs...)
var stderrBuf bytes.Buffer
var stdoutBuf bytes.Buffer
cmd.Stdout = &stdoutBuf
cmd.Stderr = &stderrBuf
return &LongRunCmd{
cmd: cmd,
cancel: cancel,
stderrBuf: stderrBuf,
stdoutBuf: stdoutBuf,
}
}
// Run in backend
func (l *LongRunCmd) Run() {
go func() {
err := l.cmd.Start()
if err != nil {
l.err = err
}
err = l.cmd.Wait()
if err != nil {
l.err = err
}
l.err = nil
l.done = true
}()
time.Sleep(time.Millisecond * 100)
}
func (l *LongRunCmd) Stop() {
l.once.Do(func() {
l.cancel()
})
}
func (l *LongRunCmd) CheckExitStatus() error {
if l.done == true {
return l.err
} else {
return fmt.Errorf("running")
}
}
func (l *LongRunCmd) GetStdoutStdErr() (string, string) {
return l.stdoutBuf.String(), l.stderrBuf.String()
}
// RunShortRunCmd defines a cmd which run and exits immediately
//
// args 命令列表
//
// dir 命令运行所在的目录
//
// envs 额外的环境变量
func RunShortRunCmd(args []string, dir string, envs []string) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
defer cancel()
cmd := exec.CommandContext(ctx, args[0], args[1:]...)
if runtime.GOOS == "windows" {
cmd = exec.CommandContext(ctx, args[0]+".exe", args[1:]...)
}
cmd.Dir = dir
cmd.Env = append(os.Environ(), envs...)
output, err := cmd.CombinedOutput()
return string(output), err
}
// SearchSymbolInBinary searches if the specified symbol is compiled into the bianry
func SearchSymbolInBinary(dir string, binary string, symbol string) (bool, error) {
if runtime.GOOS == "windows" {
binary = binary + ".exe"
}
output, err := RunShortRunCmd([]string{"go", "tool", "objdump", "-s", symbol, binary}, dir, nil)
if err != nil {
return false, fmt.Errorf("cannot lookup into the binary: %w", err)
}
return strings.Contains(output, symbol), nil
}