vendor: add gomega/gbytes and gomega/gexec
This commit is contained in:
78
vendor/github.com/onsi/gomega/gexec/build.go
generated
vendored
Normal file
78
vendor/github.com/onsi/gomega/gexec/build.go
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
package gexec
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var tmpDir string
|
||||
|
||||
/*
|
||||
Build uses go build to compile the package at packagePath. The resulting binary is saved off in a temporary directory.
|
||||
A path pointing to this binary is returned.
|
||||
|
||||
Build uses the $GOPATH set in your environment. It passes the variadic args on to `go build`.
|
||||
*/
|
||||
func Build(packagePath string, args ...string) (compiledPath string, err error) {
|
||||
return BuildIn(os.Getenv("GOPATH"), packagePath, args...)
|
||||
}
|
||||
|
||||
/*
|
||||
BuildIn is identical to Build but allows you to specify a custom $GOPATH (the first argument).
|
||||
*/
|
||||
func BuildIn(gopath string, packagePath string, args ...string) (compiledPath string, err error) {
|
||||
tmpDir, err := temporaryDirectory()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(gopath) == 0 {
|
||||
return "", errors.New("$GOPATH not provided when building " + packagePath)
|
||||
}
|
||||
|
||||
executable := filepath.Join(tmpDir, path.Base(packagePath))
|
||||
if runtime.GOOS == "windows" {
|
||||
executable = executable + ".exe"
|
||||
}
|
||||
|
||||
cmdArgs := append([]string{"build"}, args...)
|
||||
cmdArgs = append(cmdArgs, "-o", executable, packagePath)
|
||||
|
||||
build := exec.Command("go", cmdArgs...)
|
||||
build.Env = append([]string{"GOPATH=" + gopath}, os.Environ()...)
|
||||
|
||||
output, err := build.CombinedOutput()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to build %s:\n\nError:\n%s\n\nOutput:\n%s", packagePath, err, string(output))
|
||||
}
|
||||
|
||||
return executable, nil
|
||||
}
|
||||
|
||||
/*
|
||||
You should call CleanupBuildArtifacts before your test ends to clean up any temporary artifacts generated by
|
||||
gexec. In Ginkgo this is typically done in an AfterSuite callback.
|
||||
*/
|
||||
func CleanupBuildArtifacts() {
|
||||
if tmpDir != "" {
|
||||
os.RemoveAll(tmpDir)
|
||||
}
|
||||
}
|
||||
|
||||
func temporaryDirectory() (string, error) {
|
||||
var err error
|
||||
if tmpDir == "" {
|
||||
tmpDir, err = ioutil.TempDir("", "gexec_artifacts")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return ioutil.TempDir(tmpDir, "g")
|
||||
}
|
88
vendor/github.com/onsi/gomega/gexec/exit_matcher.go
generated
vendored
Normal file
88
vendor/github.com/onsi/gomega/gexec/exit_matcher.go
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
package gexec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
/*
|
||||
The Exit matcher operates on a session:
|
||||
|
||||
Ω(session).Should(Exit(<optional status code>))
|
||||
|
||||
Exit passes if the session has already exited.
|
||||
|
||||
If no status code is provided, then Exit will succeed if the session has exited regardless of exit code.
|
||||
Otherwise, Exit will only succeed if the process has exited with the provided status code.
|
||||
|
||||
Note that the process must have already exited. To wait for a process to exit, use Eventually:
|
||||
|
||||
Eventually(session, 3).Should(Exit(0))
|
||||
*/
|
||||
func Exit(optionalExitCode ...int) *exitMatcher {
|
||||
exitCode := -1
|
||||
if len(optionalExitCode) > 0 {
|
||||
exitCode = optionalExitCode[0]
|
||||
}
|
||||
|
||||
return &exitMatcher{
|
||||
exitCode: exitCode,
|
||||
}
|
||||
}
|
||||
|
||||
type exitMatcher struct {
|
||||
exitCode int
|
||||
didExit bool
|
||||
actualExitCode int
|
||||
}
|
||||
|
||||
type Exiter interface {
|
||||
ExitCode() int
|
||||
}
|
||||
|
||||
func (m *exitMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
exiter, ok := actual.(Exiter)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("Exit must be passed a gexec.Exiter (Missing method ExitCode() int) Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
|
||||
m.actualExitCode = exiter.ExitCode()
|
||||
|
||||
if m.actualExitCode == -1 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if m.exitCode == -1 {
|
||||
return true, nil
|
||||
}
|
||||
return m.exitCode == m.actualExitCode, nil
|
||||
}
|
||||
|
||||
func (m *exitMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
if m.actualExitCode == -1 {
|
||||
return "Expected process to exit. It did not."
|
||||
} else {
|
||||
return format.Message(m.actualExitCode, "to match exit code:", m.exitCode)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *exitMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
if m.actualExitCode == -1 {
|
||||
return "you really shouldn't be able to see this!"
|
||||
} else {
|
||||
if m.exitCode == -1 {
|
||||
return "Expected process not to exit. It did."
|
||||
} else {
|
||||
return format.Message(m.actualExitCode, "not to match exit code:", m.exitCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *exitMatcher) MatchMayChangeInTheFuture(actual interface{}) bool {
|
||||
session, ok := actual.(*Session)
|
||||
if ok {
|
||||
return session.ExitCode() == -1
|
||||
}
|
||||
return true
|
||||
}
|
53
vendor/github.com/onsi/gomega/gexec/prefixed_writer.go
generated
vendored
Normal file
53
vendor/github.com/onsi/gomega/gexec/prefixed_writer.go
generated
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
package gexec
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
)
|
||||
|
||||
/*
|
||||
PrefixedWriter wraps an io.Writer, emiting the passed in prefix at the beginning of each new line.
|
||||
This can be useful when running multiple gexec.Sessions concurrently - you can prefix the log output of each
|
||||
session by passing in a PrefixedWriter:
|
||||
|
||||
gexec.Start(cmd, NewPrefixedWriter("[my-cmd] ", GinkgoWriter), NewPrefixedWriter("[my-cmd] ", GinkgoWriter))
|
||||
*/
|
||||
type PrefixedWriter struct {
|
||||
prefix []byte
|
||||
writer io.Writer
|
||||
lock *sync.Mutex
|
||||
atStartOfLine bool
|
||||
}
|
||||
|
||||
func NewPrefixedWriter(prefix string, writer io.Writer) *PrefixedWriter {
|
||||
return &PrefixedWriter{
|
||||
prefix: []byte(prefix),
|
||||
writer: writer,
|
||||
lock: &sync.Mutex{},
|
||||
atStartOfLine: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *PrefixedWriter) Write(b []byte) (int, error) {
|
||||
w.lock.Lock()
|
||||
defer w.lock.Unlock()
|
||||
|
||||
toWrite := []byte{}
|
||||
|
||||
for _, c := range b {
|
||||
if w.atStartOfLine {
|
||||
toWrite = append(toWrite, w.prefix...)
|
||||
}
|
||||
|
||||
toWrite = append(toWrite, c)
|
||||
|
||||
w.atStartOfLine = c == '\n'
|
||||
}
|
||||
|
||||
_, err := w.writer.Write(toWrite)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return len(b), nil
|
||||
}
|
214
vendor/github.com/onsi/gomega/gexec/session.go
generated
vendored
Normal file
214
vendor/github.com/onsi/gomega/gexec/session.go
generated
vendored
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
Package gexec provides support for testing external processes.
|
||||
*/
|
||||
package gexec
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/gbytes"
|
||||
)
|
||||
|
||||
const INVALID_EXIT_CODE = 254
|
||||
|
||||
type Session struct {
|
||||
//The wrapped command
|
||||
Command *exec.Cmd
|
||||
|
||||
//A *gbytes.Buffer connected to the command's stdout
|
||||
Out *gbytes.Buffer
|
||||
|
||||
//A *gbytes.Buffer connected to the command's stderr
|
||||
Err *gbytes.Buffer
|
||||
|
||||
//A channel that will close when the command exits
|
||||
Exited <-chan struct{}
|
||||
|
||||
lock *sync.Mutex
|
||||
exitCode int
|
||||
}
|
||||
|
||||
/*
|
||||
Start starts the passed-in *exec.Cmd command. It wraps the command in a *gexec.Session.
|
||||
|
||||
The session pipes the command's stdout and stderr to two *gbytes.Buffers available as properties on the session: session.Out and session.Err.
|
||||
These buffers can be used with the gbytes.Say matcher to match against unread output:
|
||||
|
||||
Ω(session.Out).Should(gbytes.Say("foo-out"))
|
||||
Ω(session.Err).Should(gbytes.Say("foo-err"))
|
||||
|
||||
In addition, Session satisfies the gbytes.BufferProvider interface and provides the stdout *gbytes.Buffer. This allows you to replace the first line, above, with:
|
||||
|
||||
Ω(session).Should(gbytes.Say("foo-out"))
|
||||
|
||||
When outWriter and/or errWriter are non-nil, the session will pipe stdout and/or stderr output both into the session *gybtes.Buffers and to the passed-in outWriter/errWriter.
|
||||
This is useful for capturing the process's output or logging it to screen. In particular, when using Ginkgo it can be convenient to direct output to the GinkgoWriter:
|
||||
|
||||
session, err := Start(command, GinkgoWriter, GinkgoWriter)
|
||||
|
||||
This will log output when running tests in verbose mode, but - otherwise - will only log output when a test fails.
|
||||
|
||||
The session wrapper is responsible for waiting on the *exec.Cmd command. You *should not* call command.Wait() yourself.
|
||||
Instead, to assert that the command has exited you can use the gexec.Exit matcher:
|
||||
|
||||
Ω(session).Should(gexec.Exit())
|
||||
|
||||
When the session exits it closes the stdout and stderr gbytes buffers. This will short circuit any
|
||||
Eventuallys waiting fo the buffers to Say something.
|
||||
*/
|
||||
func Start(command *exec.Cmd, outWriter io.Writer, errWriter io.Writer) (*Session, error) {
|
||||
exited := make(chan struct{})
|
||||
|
||||
session := &Session{
|
||||
Command: command,
|
||||
Out: gbytes.NewBuffer(),
|
||||
Err: gbytes.NewBuffer(),
|
||||
Exited: exited,
|
||||
lock: &sync.Mutex{},
|
||||
exitCode: -1,
|
||||
}
|
||||
|
||||
var commandOut, commandErr io.Writer
|
||||
|
||||
commandOut, commandErr = session.Out, session.Err
|
||||
|
||||
if outWriter != nil && !reflect.ValueOf(outWriter).IsNil() {
|
||||
commandOut = io.MultiWriter(commandOut, outWriter)
|
||||
}
|
||||
|
||||
if errWriter != nil && !reflect.ValueOf(errWriter).IsNil() {
|
||||
commandErr = io.MultiWriter(commandErr, errWriter)
|
||||
}
|
||||
|
||||
command.Stdout = commandOut
|
||||
command.Stderr = commandErr
|
||||
|
||||
err := command.Start()
|
||||
if err == nil {
|
||||
go session.monitorForExit(exited)
|
||||
}
|
||||
|
||||
return session, err
|
||||
}
|
||||
|
||||
/*
|
||||
Buffer implements the gbytes.BufferProvider interface and returns s.Out
|
||||
This allows you to make gbytes.Say matcher assertions against stdout without having to reference .Out:
|
||||
|
||||
Eventually(session).Should(gbytes.Say("foo"))
|
||||
*/
|
||||
func (s *Session) Buffer() *gbytes.Buffer {
|
||||
return s.Out
|
||||
}
|
||||
|
||||
/*
|
||||
ExitCode returns the wrapped command's exit code. If the command hasn't exited yet, ExitCode returns -1.
|
||||
|
||||
To assert that the command has exited it is more convenient to use the Exit matcher:
|
||||
|
||||
Eventually(s).Should(gexec.Exit())
|
||||
|
||||
When the process exits because it has received a particular signal, the exit code will be 128+signal-value
|
||||
(See http://www.tldp.org/LDP/abs/html/exitcodes.html and http://man7.org/linux/man-pages/man7/signal.7.html)
|
||||
|
||||
*/
|
||||
func (s *Session) ExitCode() int {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
return s.exitCode
|
||||
}
|
||||
|
||||
/*
|
||||
Wait waits until the wrapped command exits. It can be passed an optional timeout.
|
||||
If the command does not exit within the timeout, Wait will trigger a test failure.
|
||||
|
||||
Wait returns the session, making it possible to chain:
|
||||
|
||||
session.Wait().Out.Contents()
|
||||
|
||||
will wait for the command to exit then return the entirety of Out's contents.
|
||||
|
||||
Wait uses eventually under the hood and accepts the same timeout/polling intervals that eventually does.
|
||||
*/
|
||||
func (s *Session) Wait(timeout ...interface{}) *Session {
|
||||
EventuallyWithOffset(1, s, timeout...).Should(Exit())
|
||||
return s
|
||||
}
|
||||
|
||||
/*
|
||||
Kill sends the running command a SIGKILL signal. It does not wait for the process to exit.
|
||||
|
||||
If the command has already exited, Kill returns silently.
|
||||
|
||||
The session is returned to enable chaining.
|
||||
*/
|
||||
func (s *Session) Kill() *Session {
|
||||
if s.ExitCode() != -1 {
|
||||
return s
|
||||
}
|
||||
s.Command.Process.Kill()
|
||||
return s
|
||||
}
|
||||
|
||||
/*
|
||||
Interrupt sends the running command a SIGINT signal. It does not wait for the process to exit.
|
||||
|
||||
If the command has already exited, Interrupt returns silently.
|
||||
|
||||
The session is returned to enable chaining.
|
||||
*/
|
||||
func (s *Session) Interrupt() *Session {
|
||||
return s.Signal(syscall.SIGINT)
|
||||
}
|
||||
|
||||
/*
|
||||
Terminate sends the running command a SIGTERM signal. It does not wait for the process to exit.
|
||||
|
||||
If the command has already exited, Terminate returns silently.
|
||||
|
||||
The session is returned to enable chaining.
|
||||
*/
|
||||
func (s *Session) Terminate() *Session {
|
||||
return s.Signal(syscall.SIGTERM)
|
||||
}
|
||||
|
||||
/*
|
||||
Terminate sends the running command the passed in signal. It does not wait for the process to exit.
|
||||
|
||||
If the command has already exited, Signal returns silently.
|
||||
|
||||
The session is returned to enable chaining.
|
||||
*/
|
||||
func (s *Session) Signal(signal os.Signal) *Session {
|
||||
if s.ExitCode() != -1 {
|
||||
return s
|
||||
}
|
||||
s.Command.Process.Signal(signal)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Session) monitorForExit(exited chan<- struct{}) {
|
||||
err := s.Command.Wait()
|
||||
s.lock.Lock()
|
||||
s.Out.Close()
|
||||
s.Err.Close()
|
||||
status := s.Command.ProcessState.Sys().(syscall.WaitStatus)
|
||||
if status.Signaled() {
|
||||
s.exitCode = 128 + int(status.Signal())
|
||||
} else {
|
||||
exitStatus := status.ExitStatus()
|
||||
if exitStatus == -1 && err != nil {
|
||||
s.exitCode = INVALID_EXIT_CODE
|
||||
}
|
||||
s.exitCode = exitStatus
|
||||
}
|
||||
s.lock.Unlock()
|
||||
|
||||
close(exited)
|
||||
}
|
Reference in New Issue
Block a user