Skip to content

Commit

Permalink
Update stubcmd
Browse files Browse the repository at this point in the history
  • Loading branch information
k1LoW committed Jul 28, 2019
1 parent d5006f9 commit a9e2b6b
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 81 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
coverage.txt
coverage.txt
testdata/stubcmd
21 changes: 6 additions & 15 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,51 +4,42 @@ matrix:
- go: 1.12.x
os: linux
env: GO111MODULE=on
before_install:
- echo $TRAVIS_GO_VERSION
- sudo pip install codecov
after_success:
- codecov
- go: master
os: linux
env: GO111MODULE=on
before_install:
- echo $TRAVIS_GO_VERSION
- sudo pip install codecov
- go: 1.12.x
os: osx
env: GO111MODULE=on
before_install:
- echo $TRAVIS_GO_VERSION
- go: master
os: osx
env: GO111MODULE=on
before_install:
- echo $TRAVIS_GO_VERSION
- go: 1.12.x
os: windows
env:
- GO111MODULE=on
before_install:
- echo $TRAVIS_GO_VERSION
- echo $PATH
- echo $GOPATH
- ps aux
- echo $TERM
script:
- go test -v
after_script:
- ps aux
- go: master
os: windows
env:
- GO111MODULE=on
before_install:
- echo $TRAVIS_GO_VERSION
- echo $TERM
script:
- go test -v
after_script:
- ps aux
allow_failures:
- go: master
before_install:
- echo $TRAVIS_GO_VERSION
- echo $TERM
- sudo pip install codecov
script:
- make ci
111 changes: 53 additions & 58 deletions exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,26 @@ import (
"bytes"
"context"
"fmt"
"math/rand"
"os"
"os/exec"
"runtime"
"strconv"
"strings"
"syscall"
"testing"
"time"
)

var (
stubCmd = `.\testdata\stubcmd.exe`
shellcmd = `/bin/sh`
shellflag = "-c"
stubCmd = `./testdata/stubcmd`
)

func init() {
if runtime.GOOS != "windows" {
return
if runtime.GOOS == "windows" {
shellcmd = "cmd"
shellflag = "/c"
stubCmd = `.\testdata\stubcmd.exe`
}
err := exec.Command("go", "build", "-o", stubCmd, "testdata/stubcmd.go").Run()
if err != nil {
Expand All @@ -41,14 +43,13 @@ func TestCommand(t *testing.T) {
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
t.Fatalf("%s: %v", tt.name, err)
t.Errorf("%v: %v", tt.cmd, err)
}
if strings.TrimRight(stdout.String(), "\n\r") != tt.want {
t.Errorf("%s: want = %#v, got = %#v", tt.name, tt.want, stdout.String())
t.Errorf("%v: want = %#v, got = %#v", tt.cmd, tt.want, stdout.String())
}
out, err := exec.Command("bash", "-c", fmt.Sprintf("ps aux | grep %s | grep -v grep", tt.want)).Output()
if err == nil || string(out) != "" {
t.Errorf("%s", "the process has not exited")
if checkprocess() {
t.Errorf("%v: %s", tt.cmd, "the process has not exited")
}
}
}
Expand All @@ -66,14 +67,13 @@ func TestCommandContext(t *testing.T) {
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
t.Fatalf("%s: %v", tt.name, err)
t.Fatalf("%v: %v", tt.cmd, err)
}
if strings.TrimRight(stdout.String(), "\n\r") != tt.want {
t.Errorf("%s: want = %#v, got = %#v", tt.name, tt.want, stdout.String())
t.Errorf("%v: want = %#v, got = %#v", tt.cmd, tt.want, stdout.String())
}
out, err := exec.Command("bash", "-c", fmt.Sprintf("ps aux | grep %s | grep -v grep", tt.want)).Output()
if err == nil || string(out) != "" {
t.Errorf("%s", "the process has not exited")
if checkprocess() {
t.Errorf("%v: %s", tt.cmd, "the process has not exited")
}
}
}
Expand All @@ -92,16 +92,17 @@ func TestCommandContextCancel(t *testing.T) {
cmd.Stderr = &stderr
err := cmd.Start()
if err != nil {
t.Fatalf("%s: %v", tt.name, err)
t.Fatalf("%v: %v", tt.cmd, err)
}
go func() {
cmd.Wait()
}()
time.Sleep(100 * time.Millisecond)
if !checkprocess() && !tt.processFinished {
t.Fatalf("%v: %s", tt.cmd, "the process has been exited")
}
cancel()
out, err := exec.Command("bash", "-c", fmt.Sprintf("ps aux | grep %s | grep -v grep", tt.want)).Output()
if err == nil || string(out) != "" {
t.Errorf("%s", "the process has not exited")
if checkprocess() {
t.Errorf("%v: %s", tt.cmd, "the process has not exited")
}
}
}
Expand All @@ -118,12 +119,14 @@ func TestTerminateCommand(t *testing.T) {
cmd.Stderr = &stderr
err := cmd.Start()
if err != nil {
t.Fatalf("%v", err)
t.Fatalf("%v: %v", tt.cmd, err)
}
go func() {
cmd.Wait()
}()
time.Sleep(500 * time.Millisecond)
if !checkprocess() && !tt.processFinished {
t.Fatalf("%v: %s", tt.cmd, "the process has been exited")
}
if runtime.GOOS == "windows" {
sig := os.Interrupt
err = TerminateCommand(cmd, sig)
Expand All @@ -132,11 +135,10 @@ func TestTerminateCommand(t *testing.T) {
err = TerminateCommand(cmd, sig)
}
if err != nil && !tt.processFinished {
t.Errorf("%s: %v", tt.name, err)
t.Errorf("%v: %v", tt.cmd, err)
}
out, err := exec.Command("bash", "-c", fmt.Sprintf("ps aux | grep %s | grep -v grep", tt.want)).Output()
if err == nil || string(out) != "" {
t.Errorf("%s: %s", tt.name, "the process has not exited")
if checkprocess() {
t.Errorf("%v: %s", tt.cmd, "the process has not exited")
}
}
}
Expand All @@ -153,19 +155,20 @@ func TestKillCommand(t *testing.T) {
cmd.Stderr = &stderr
err := cmd.Start()
if err != nil {
t.Fatalf("%v", err)
t.Fatalf("%v: %v", tt.cmd, err)
}
go func() {
cmd.Wait()
}()
time.Sleep(500 * time.Millisecond)
if !checkprocess() && !tt.processFinished {
t.Fatalf("%v: %s", tt.cmd, "the process has been exited")
}
err = KillCommand(cmd)
if err != nil && !tt.processFinished {
t.Fatalf("%s: %v", tt.name, err)
t.Fatalf("%v: %v", tt.cmd, err)
}
out, err := exec.Command("bash", "-c", fmt.Sprintf("ps aux | grep %s | grep -v grep", tt.want)).Output()
if err == nil || string(out) != "" {
t.Errorf("%s: %s", tt.name, "the process has not exited")
if checkprocess() {
t.Errorf("%v: %s", tt.cmd, "the process has not exited")
}
}
}
Expand All @@ -177,35 +180,27 @@ type testcase struct {
processFinished bool
}

func gentests(withSleepTest bool) []testcase {
tests := []testcase{}
func checkprocess() bool {
time.Sleep(500 * time.Millisecond)
var (
out []byte
err error
)
if runtime.GOOS == "windows" {
// r := random()
// tests = append(tests, testcase{"echo", []string{"echo", r}, r, true})
// r = random()
// tests = append(tests, testcase{"cmd /c echo", []string{"cmd", "/c", fmt.Sprintf("echo %s", r)}, r, true})
// if withSleepTest {
// r = "123456"
// tests = append(tests, testcase{"sleep", []string{stubCmd, "-sleep", r}, r, false})
// r = "654321"
// tests = append(tests, testcase{"cmd /c sleep", []string{"cmd", "/c", fmt.Sprintf("%s -sleep %s", stubCmd, r)}, r, false})
// }
// return tests
out, err = exec.Command("cmd", "/c", "tasklist | grep stubcmd.exe | grep -v grep").Output()
} else {
out, err = exec.Command("bash", "-c", "ps aux | grep stubcmd | grep -v grep").Output()
}
r := random()
tests = append(tests, testcase{"echo", []string{"echo", r}, r, true})
r = random()
tests = append(tests, testcase{"bash -c echo", []string{"bash", "-c", fmt.Sprintf("echo %s", r)}, r, true})
return (err == nil || strings.TrimRight(string(out), "\n\r") != "")
}

func gentests(withSleepTest bool) []testcase {
tests := []testcase{}
tests = append(tests, testcase{"echo", []string{stubCmd, "-echo", "!!!"}, "!!!", true})
tests = append(tests, testcase{"sh -c echo", []string{shellcmd, shellflag, fmt.Sprintf("%s -echo %s", stubCmd, "!!!")}, "!!!", true})
if withSleepTest {
r = "123456"
tests = append(tests, testcase{"sleep", []string{"sleep", r}, r, false})
r = "654321"
tests = append(tests, testcase{"bash -c sleep", []string{"bash", "-c", fmt.Sprintf("sleep %s && echo %s", r, r)}, r, false})
tests = append(tests, testcase{"sleep", []string{stubCmd, "-sleep", "10", "-echo", "!!!"}, "!!!", false})
tests = append(tests, testcase{"sh -c sleep", []string{shellcmd, shellflag, fmt.Sprintf("%s -sleep %s -echo %s", stubCmd, "10", "!!!")}, "!!!", false})
}
return tests
}

func random() string {
rand.Seed(time.Now().UnixNano())
return strconv.Itoa(rand.Int())
}
42 changes: 39 additions & 3 deletions exec_windows.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package exec

import (
"errors"
"fmt"
"os"
"os/exec"
"strconv"
"strings"
"syscall"

"github.com/mattn/psutil"
)

// MEMO: Sending Interrupt on Windows is not implemented.
Expand All @@ -24,12 +26,46 @@ func command(name string, arg ...string) *exec.Cmd {
}

func terminate(cmd *exec.Cmd, sig os.Signal) error {
if os.Getenv("TERM") == "cygwin" {
return killall(cmd) // fallback
}
if err := cmd.Process.Signal(sig); err != nil {
return killall(cmd) // fallback
}
return nil
}

func killall(cmd *exec.Cmd) error {
return psutil.TerminateTree(cmd.Process.Pid, -1)
var err error
wpid := cmd.Process.Pid
if os.Getenv("TERM") == "cygwin" {
wpid, err = winpid(cmd.Process.Pid)
if err != nil {
return err
}
}

return exec.Command("taskkill", "/F", "/T", "/PID", strconv.Itoa(wpid)).Run()
// return psutil.TerminateTree(cmd.Process.Pid, 0)
}

// winpid convert cygwin pid -> windows pid
func winpid(pid int) (int, error) {
winpidCmd := exec.Command("cat", fmt.Sprintf("/proc/%d/winpid", pid))
out, err := winpidCmd.Output()
if err != nil {
out, err = exec.Command("tasklist", "/FI", fmt.Sprintf("PID eq %d", pid)).Output()
if err != nil {
return pid, err
}
if !strings.Contains(string(out), strconv.Itoa(pid)) {
return pid, errors.New("process does not exist")
}
return pid, nil
}
winpid, err := strconv.Atoi(strings.TrimRight(string(out), "\n\r"))
if err != nil {
return pid, err
}
return winpid, nil
}
2 changes: 0 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
module github.com/k1LoW/exec

go 1.12

require github.com/mattn/psutil v0.0.0-20170126005127-e6c88f1e9be6 // indirect
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +0,0 @@
github.com/mattn/psutil v0.0.0-20170126005127-e6c88f1e9be6 h1:O8ALYd1Y//vPCaZ1iM8gjrOnEGuXzaaDuZX+7ibLxNg=
github.com/mattn/psutil v0.0.0-20170126005127-e6c88f1e9be6/go.mod h1:LmHOQPTLqN7r9tuLmqA3xdiqTnFjuzF7sXVoILxjxa4=
6 changes: 6 additions & 0 deletions testdata/stubcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@ package main

import (
"flag"
"fmt"
"time"
)

func main() {
var (
sleep = flag.Int("sleep", 0, "sleep sec")
echo = flag.String("echo", "", "echo string")
)
flag.Parse()

if *sleep > 0 {
time.Sleep(time.Duration(*sleep) * time.Second)
}

if *echo != "" {
fmt.Printf("%s\n", *echo)
}
}

0 comments on commit a9e2b6b

Please sign in to comment.