-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #30 from SimonBaeumer/gofmt-fixes
Gofmt fixes
- Loading branch information
Showing
13 changed files
with
621 additions
and
609 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,124 +1,125 @@ | ||
package cmd | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"log" | ||
"os/exec" | ||
"strings" | ||
"syscall" | ||
"time" | ||
"bytes" | ||
"fmt" | ||
"log" | ||
"os/exec" | ||
"strings" | ||
"syscall" | ||
"time" | ||
) | ||
|
||
//Command represents a single command which can be executed | ||
type Command struct { | ||
Cmd string | ||
Env []string | ||
Dir string | ||
Timeout time.Duration | ||
executed bool | ||
stderr string | ||
stdout string | ||
exitCode int | ||
Cmd string | ||
Env []string | ||
Dir string | ||
Timeout time.Duration | ||
executed bool | ||
stderr string | ||
stdout string | ||
exitCode int | ||
} | ||
|
||
//NewCommand creates a new command | ||
func NewCommand(cmd string) *Command { | ||
return &Command{ | ||
Cmd: cmd, | ||
Timeout: 1 * time.Minute, | ||
executed: false, | ||
} | ||
return &Command{ | ||
Cmd: cmd, | ||
Timeout: 1 * time.Minute, | ||
executed: false, | ||
} | ||
} | ||
|
||
//SetTimeoutMS sets the timeout in milliseconds | ||
func (c *Command) SetTimeoutMS(ms int) { | ||
if ms == 0 { | ||
c.Timeout = 1 * time.Minute | ||
} | ||
c.Timeout = time.Duration(ms) * time.Millisecond | ||
if ms == 0 { | ||
c.Timeout = 1 * time.Minute | ||
} | ||
c.Timeout = time.Duration(ms) * time.Millisecond | ||
} | ||
|
||
//Stdout returns the output to stdout | ||
func (c *Command) Stdout() string { | ||
c.isExecuted("Stdout") | ||
return c.stdout | ||
c.isExecuted("Stdout") | ||
return c.stdout | ||
} | ||
|
||
//Stderr returns the output to stderr | ||
func (c *Command) Stderr() string { | ||
c.isExecuted("Stderr") | ||
return c.stderr | ||
c.isExecuted("Stderr") | ||
return c.stderr | ||
} | ||
|
||
//ExitCode returns the exit code of the command | ||
func (c *Command) ExitCode() int { | ||
c.isExecuted("ExitCode") | ||
return c.exitCode | ||
c.isExecuted("ExitCode") | ||
return c.exitCode | ||
} | ||
|
||
//Executed returns if the command was already executed | ||
func (c *Command) Executed() bool { | ||
return c.executed | ||
return c.executed | ||
} | ||
|
||
func (c *Command) isExecuted(property string) { | ||
if !c.executed { | ||
panic("Can not read " + property + " if command was not executed.") | ||
} | ||
if !c.executed { | ||
panic("Can not read " + property + " if command was not executed.") | ||
} | ||
} | ||
|
||
//Execute executes the commande | ||
func (c *Command) Execute() error { | ||
cmd := exec.Command("sh", "-c", c.Cmd) | ||
cmd.Env = c.Env | ||
cmd.Dir = c.Dir | ||
|
||
var ( | ||
outBuff bytes.Buffer | ||
errBuff bytes.Buffer | ||
) | ||
cmd.Stdout = &outBuff | ||
cmd.Stderr = &errBuff | ||
|
||
err := cmd.Start() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
done := make(chan error) | ||
go func() { | ||
done <- cmd.Wait() | ||
}() | ||
|
||
select { | ||
case err := <- done: | ||
if err != nil { | ||
log.Println("Command exited with error", c.Cmd, err.Error()) | ||
c.getExitCode(err) | ||
break | ||
} | ||
log.Println("Command exited successfully", c.Cmd) | ||
c.exitCode = 0 | ||
case <- time.After(c.Timeout): | ||
log.Println("Command timed out", c.Cmd) | ||
if err := cmd.Process.Kill(); err != nil { | ||
return fmt.Errorf("Timeout occured and can not kill process with pid %v", cmd.Process.Pid) | ||
} | ||
return fmt.Errorf("Command timed out after %v", c.Timeout) | ||
} | ||
|
||
// Remove leading and trailing whitespaces | ||
c.stderr = strings.Trim(errBuff.String(), "\n") | ||
c.stdout = strings.Trim(outBuff.String(), "\n") | ||
c.executed = true | ||
|
||
return nil | ||
cmd := exec.Command("sh", "-c", c.Cmd) | ||
cmd.Env = c.Env | ||
cmd.Dir = c.Dir | ||
|
||
var ( | ||
outBuff bytes.Buffer | ||
errBuff bytes.Buffer | ||
) | ||
cmd.Stdout = &outBuff | ||
cmd.Stderr = &errBuff | ||
|
||
err := cmd.Start() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
done := make(chan error) | ||
go func() { | ||
done <- cmd.Wait() | ||
}() | ||
|
||
select { | ||
case err := <-done: | ||
if err != nil { | ||
log.Println("Command exited with error", c.Cmd, err.Error()) | ||
c.getExitCode(err) | ||
break | ||
} | ||
log.Println("Command exited successfully", c.Cmd) | ||
c.exitCode = 0 | ||
case <-time.After(c.Timeout): | ||
log.Println("Command timed out", c.Cmd) | ||
if err := cmd.Process.Kill(); err != nil { | ||
return fmt.Errorf("Timeout occurred and can not kill process with pid %v", cmd.Process.Pid) | ||
} | ||
return fmt.Errorf("Command timed out after %v", c.Timeout) | ||
} | ||
|
||
// Remove leading and trailing whitespaces | ||
c.stderr = strings.Trim(errBuff.String(), "\n") | ||
c.stdout = strings.Trim(outBuff.String(), "\n") | ||
c.executed = true | ||
|
||
return nil | ||
} | ||
|
||
func (c *Command) getExitCode(err error) { | ||
if exitErr, ok := err.(*exec.ExitError); ok { | ||
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { | ||
c.exitCode = status.ExitStatus() | ||
} | ||
} | ||
if exitErr, ok := err.(*exec.ExitError); ok { | ||
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok { | ||
c.exitCode = status.ExitStatus() | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,67 @@ | ||
package cmd | ||
|
||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
func TestCommand_NewCommand(t *testing.T) { | ||
cmd := NewCommand("") | ||
assert.False(t, cmd.Executed()) | ||
cmd := NewCommand("") | ||
assert.False(t, cmd.Executed()) | ||
} | ||
|
||
func TestCommand_Execute(t *testing.T) { | ||
cmd := NewCommand("/bin/echo hello") | ||
cmd := NewCommand("/bin/echo hello") | ||
|
||
err := cmd.Execute() | ||
err := cmd.Execute() | ||
|
||
assert.Nil(t, err) | ||
assert.True(t, cmd.Executed()) | ||
assert.Equal(t, cmd.Stdout(), "hello") | ||
assert.Nil(t, err) | ||
assert.True(t, cmd.Executed()) | ||
assert.Equal(t, cmd.Stdout(), "hello") | ||
} | ||
|
||
func TestCommand_ExecuteStderr(t *testing.T) { | ||
cmd := NewCommand(">&2 /bin/echo hello") | ||
cmd := NewCommand(">&2 /bin/echo hello") | ||
|
||
err := cmd.Execute() | ||
err := cmd.Execute() | ||
|
||
assert.Nil(t, err) | ||
assert.Equal(t, "hello", cmd.Stderr()) | ||
assert.Nil(t, err) | ||
assert.Equal(t, "hello", cmd.Stderr()) | ||
} | ||
|
||
func TestCommand_ExitCode(t *testing.T) { | ||
cmd := NewCommand("exit 120") | ||
cmd := NewCommand("exit 120") | ||
|
||
err := cmd.Execute() | ||
err := cmd.Execute() | ||
|
||
assert.Nil(t, err) | ||
assert.Equal(t, 120, cmd.ExitCode()) | ||
assert.Nil(t, err) | ||
assert.Equal(t, 120, cmd.ExitCode()) | ||
} | ||
|
||
func TestCommand_WithEnvVariables(t *testing.T) { | ||
cmd := NewCommand("echo $TEST") | ||
cmd.Env = []string{"TEST=hey"} | ||
cmd := NewCommand("echo $TEST") | ||
cmd.Env = []string{"TEST=hey"} | ||
|
||
_ = cmd.Execute() | ||
_ = cmd.Execute() | ||
|
||
assert.Equal(t, "hey", cmd.Stdout()) | ||
assert.Equal(t, "hey", cmd.Stdout()) | ||
} | ||
|
||
func TestCommand_WithTimeout(t *testing.T) { | ||
cmd := NewCommand("sleep 0.005;") | ||
cmd.SetTimeoutMS(5) | ||
cmd := NewCommand("sleep 0.005;") | ||
cmd.SetTimeoutMS(5) | ||
|
||
err := cmd.Execute() | ||
err := cmd.Execute() | ||
|
||
assert.NotNil(t, err) | ||
assert.Equal(t, "Command timed out after 5ms", err.Error()) | ||
assert.NotNil(t, err) | ||
assert.Equal(t, "Command timed out after 5ms", err.Error()) | ||
} | ||
|
||
func TestCommand_WithValidTimeout(t *testing.T) { | ||
cmd := NewCommand("sleep 0.01;") | ||
cmd.SetTimeoutMS(500) | ||
cmd := NewCommand("sleep 0.01;") | ||
cmd.SetTimeoutMS(500) | ||
|
||
err := cmd.Execute() | ||
err := cmd.Execute() | ||
|
||
assert.Nil(t, err) | ||
assert.Nil(t, err) | ||
} |
Oops, something went wrong.