Update go dependencies
This commit is contained in:
parent
c639f490b1
commit
d3c957192e
125 changed files with 12284 additions and 0 deletions
245
vendor/github.com/onsi/gomega/gbytes/buffer.go
generated
vendored
Normal file
245
vendor/github.com/onsi/gomega/gbytes/buffer.go
generated
vendored
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
Package gbytes provides a buffer that supports incrementally detecting input.
|
||||
|
||||
You use gbytes.Buffer with the gbytes.Say matcher. When Say finds a match, it fastforwards the buffer's read cursor to the end of that match.
|
||||
|
||||
Subsequent matches against the buffer will only operate against data that appears *after* the read cursor.
|
||||
|
||||
The read cursor is an opaque implementation detail that you cannot access. You should use the Say matcher to sift through the buffer. You can always
|
||||
access the entire buffer's contents with Contents().
|
||||
|
||||
*/
|
||||
package gbytes
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
/*
|
||||
gbytes.Buffer implements an io.Writer and can be used with the gbytes.Say matcher.
|
||||
|
||||
You should only use a gbytes.Buffer in test code. It stores all writes in an in-memory buffer - behavior that is inappropriate for production code!
|
||||
*/
|
||||
type Buffer struct {
|
||||
contents []byte
|
||||
readCursor uint64
|
||||
lock *sync.Mutex
|
||||
detectCloser chan interface{}
|
||||
closed bool
|
||||
}
|
||||
|
||||
/*
|
||||
NewBuffer returns a new gbytes.Buffer
|
||||
*/
|
||||
func NewBuffer() *Buffer {
|
||||
return &Buffer{
|
||||
lock: &sync.Mutex{},
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
BufferWithBytes returns a new gbytes.Buffer seeded with the passed in bytes
|
||||
*/
|
||||
func BufferWithBytes(bytes []byte) *Buffer {
|
||||
return &Buffer{
|
||||
lock: &sync.Mutex{},
|
||||
contents: bytes,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
BufferReader returns a new gbytes.Buffer that wraps a reader. The reader's contents are read into
|
||||
the Buffer via io.Copy
|
||||
*/
|
||||
func BufferReader(reader io.Reader) *Buffer {
|
||||
b := &Buffer{
|
||||
lock: &sync.Mutex{},
|
||||
}
|
||||
|
||||
go func() {
|
||||
io.Copy(b, reader)
|
||||
b.Close()
|
||||
}()
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
/*
|
||||
Write implements the io.Writer interface
|
||||
*/
|
||||
func (b *Buffer) Write(p []byte) (n int, err error) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.closed {
|
||||
return 0, errors.New("attempt to write to closed buffer")
|
||||
}
|
||||
|
||||
b.contents = append(b.contents, p...)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
/*
|
||||
Read implements the io.Reader interface. It advances the
|
||||
cursor as it reads.
|
||||
|
||||
Returns an error if called after Close.
|
||||
*/
|
||||
func (b *Buffer) Read(d []byte) (int, error) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.closed {
|
||||
return 0, errors.New("attempt to read from closed buffer")
|
||||
}
|
||||
|
||||
if uint64(len(b.contents)) <= b.readCursor {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
n := copy(d, b.contents[b.readCursor:])
|
||||
b.readCursor += uint64(n)
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
/*
|
||||
Close signifies that the buffer will no longer be written to
|
||||
*/
|
||||
func (b *Buffer) Close() error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.closed = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
Closed returns true if the buffer has been closed
|
||||
*/
|
||||
func (b *Buffer) Closed() bool {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
return b.closed
|
||||
}
|
||||
|
||||
/*
|
||||
Contents returns all data ever written to the buffer.
|
||||
*/
|
||||
func (b *Buffer) Contents() []byte {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
contents := make([]byte, len(b.contents))
|
||||
copy(contents, b.contents)
|
||||
return contents
|
||||
}
|
||||
|
||||
/*
|
||||
Detect takes a regular expression and returns a channel.
|
||||
|
||||
The channel will receive true the first time data matching the regular expression is written to the buffer.
|
||||
The channel is subsequently closed and the buffer's read-cursor is fast-forwarded to just after the matching region.
|
||||
|
||||
You typically don't need to use Detect and should use the ghttp.Say matcher instead. Detect is useful, however, in cases where your code must
|
||||
be branch and handle different outputs written to the buffer.
|
||||
|
||||
For example, consider a buffer hooked up to the stdout of a client library. You may (or may not, depending on state outside of your control) need to authenticate the client library.
|
||||
|
||||
You could do something like:
|
||||
|
||||
select {
|
||||
case <-buffer.Detect("You are not logged in"):
|
||||
//log in
|
||||
case <-buffer.Detect("Success"):
|
||||
//carry on
|
||||
case <-time.After(time.Second):
|
||||
//welp
|
||||
}
|
||||
buffer.CancelDetects()
|
||||
|
||||
You should always call CancelDetects after using Detect. This will close any channels that have not detected and clean up the goroutines that were spawned to support them.
|
||||
|
||||
Finally, you can pass detect a format string followed by variadic arguments. This will construct the regexp using fmt.Sprintf.
|
||||
*/
|
||||
func (b *Buffer) Detect(desired string, args ...interface{}) chan bool {
|
||||
formattedRegexp := desired
|
||||
if len(args) > 0 {
|
||||
formattedRegexp = fmt.Sprintf(desired, args...)
|
||||
}
|
||||
re := regexp.MustCompile(formattedRegexp)
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.detectCloser == nil {
|
||||
b.detectCloser = make(chan interface{})
|
||||
}
|
||||
|
||||
closer := b.detectCloser
|
||||
response := make(chan bool)
|
||||
go func() {
|
||||
ticker := time.NewTicker(10 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
defer close(response)
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
b.lock.Lock()
|
||||
data, cursor := b.contents[b.readCursor:], b.readCursor
|
||||
loc := re.FindIndex(data)
|
||||
b.lock.Unlock()
|
||||
|
||||
if loc != nil {
|
||||
response <- true
|
||||
b.lock.Lock()
|
||||
newCursorPosition := cursor + uint64(loc[1])
|
||||
if newCursorPosition >= b.readCursor {
|
||||
b.readCursor = newCursorPosition
|
||||
}
|
||||
b.lock.Unlock()
|
||||
return
|
||||
}
|
||||
case <-closer:
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
/*
|
||||
CancelDetects cancels any pending detects and cleans up their goroutines. You should always call this when you're done with a set of Detect channels.
|
||||
*/
|
||||
func (b *Buffer) CancelDetects() {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
close(b.detectCloser)
|
||||
b.detectCloser = nil
|
||||
}
|
||||
|
||||
func (b *Buffer) didSay(re *regexp.Regexp) (bool, []byte) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
unreadBytes := b.contents[b.readCursor:]
|
||||
copyOfUnreadBytes := make([]byte, len(unreadBytes))
|
||||
copy(copyOfUnreadBytes, unreadBytes)
|
||||
|
||||
loc := re.FindIndex(unreadBytes)
|
||||
|
||||
if loc != nil {
|
||||
b.readCursor += uint64(loc[1])
|
||||
return true, copyOfUnreadBytes
|
||||
}
|
||||
return false, copyOfUnreadBytes
|
||||
}
|
||||
85
vendor/github.com/onsi/gomega/gbytes/io_wrappers.go
generated
vendored
Normal file
85
vendor/github.com/onsi/gomega/gbytes/io_wrappers.go
generated
vendored
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
package gbytes
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ErrTimeout is returned by TimeoutCloser, TimeoutReader, and TimeoutWriter when the underlying Closer/Reader/Writer does not return within the specified timeout
|
||||
var ErrTimeout = errors.New("timeout occurred")
|
||||
|
||||
// TimeoutCloser returns an io.Closer that wraps the passed-in io.Closer. If the underlying Closer fails to close within the alloted timeout ErrTimeout is returned.
|
||||
func TimeoutCloser(c io.Closer, timeout time.Duration) io.Closer {
|
||||
return timeoutReaderWriterCloser{c: c, d: timeout}
|
||||
}
|
||||
|
||||
// TimeoutReader returns an io.Reader that wraps the passed-in io.Reader. If the underlying Reader fails to read within the alloted timeout ErrTimeout is returned.
|
||||
func TimeoutReader(r io.Reader, timeout time.Duration) io.Reader {
|
||||
return timeoutReaderWriterCloser{r: r, d: timeout}
|
||||
}
|
||||
|
||||
// TimeoutWriter returns an io.Writer that wraps the passed-in io.Writer. If the underlying Writer fails to write within the alloted timeout ErrTimeout is returned.
|
||||
func TimeoutWriter(w io.Writer, timeout time.Duration) io.Writer {
|
||||
return timeoutReaderWriterCloser{w: w, d: timeout}
|
||||
}
|
||||
|
||||
type timeoutReaderWriterCloser struct {
|
||||
c io.Closer
|
||||
w io.Writer
|
||||
r io.Reader
|
||||
d time.Duration
|
||||
}
|
||||
|
||||
func (t timeoutReaderWriterCloser) Close() error {
|
||||
done := make(chan struct{})
|
||||
var err error
|
||||
|
||||
go func() {
|
||||
err = t.c.Close()
|
||||
close(done)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
return err
|
||||
case <-time.After(t.d):
|
||||
return ErrTimeout
|
||||
}
|
||||
}
|
||||
|
||||
func (t timeoutReaderWriterCloser) Read(p []byte) (int, error) {
|
||||
done := make(chan struct{})
|
||||
var n int
|
||||
var err error
|
||||
|
||||
go func() {
|
||||
n, err = t.r.Read(p)
|
||||
close(done)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
return n, err
|
||||
case <-time.After(t.d):
|
||||
return 0, ErrTimeout
|
||||
}
|
||||
}
|
||||
|
||||
func (t timeoutReaderWriterCloser) Write(p []byte) (int, error) {
|
||||
done := make(chan struct{})
|
||||
var n int
|
||||
var err error
|
||||
|
||||
go func() {
|
||||
n, err = t.w.Write(p)
|
||||
close(done)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
return n, err
|
||||
case <-time.After(t.d):
|
||||
return 0, ErrTimeout
|
||||
}
|
||||
}
|
||||
104
vendor/github.com/onsi/gomega/gbytes/say_matcher.go
generated
vendored
Normal file
104
vendor/github.com/onsi/gomega/gbytes/say_matcher.go
generated
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
package gbytes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
//Objects satisfying the BufferProvider can be used with the Say matcher.
|
||||
type BufferProvider interface {
|
||||
Buffer() *Buffer
|
||||
}
|
||||
|
||||
/*
|
||||
Say is a Gomega matcher that operates on gbytes.Buffers:
|
||||
|
||||
Expect(buffer).Should(Say("something"))
|
||||
|
||||
will succeed if the unread portion of the buffer matches the regular expression "something".
|
||||
|
||||
When Say succeeds, it fast forwards the gbytes.Buffer's read cursor to just after the succesful match.
|
||||
Thus, subsequent calls to Say will only match against the unread portion of the buffer
|
||||
|
||||
Say pairs very well with Eventually. To assert that a buffer eventually receives data matching "[123]-star" within 3 seconds you can:
|
||||
|
||||
Eventually(buffer, 3).Should(Say("[123]-star"))
|
||||
|
||||
Ditto with consistently. To assert that a buffer does not receive data matching "never-see-this" for 1 second you can:
|
||||
|
||||
Consistently(buffer, 1).ShouldNot(Say("never-see-this"))
|
||||
|
||||
In addition to bytes.Buffers, Say can operate on objects that implement the gbytes.BufferProvider interface.
|
||||
In such cases, Say simply operates on the *gbytes.Buffer returned by Buffer()
|
||||
|
||||
If the buffer is closed, the Say matcher will tell Eventually to abort.
|
||||
*/
|
||||
func Say(expected string, args ...interface{}) *sayMatcher {
|
||||
if len(args) > 0 {
|
||||
expected = fmt.Sprintf(expected, args...)
|
||||
}
|
||||
return &sayMatcher{
|
||||
re: regexp.MustCompile(expected),
|
||||
}
|
||||
}
|
||||
|
||||
type sayMatcher struct {
|
||||
re *regexp.Regexp
|
||||
receivedSayings []byte
|
||||
}
|
||||
|
||||
func (m *sayMatcher) buffer(actual interface{}) (*Buffer, bool) {
|
||||
var buffer *Buffer
|
||||
|
||||
switch x := actual.(type) {
|
||||
case *Buffer:
|
||||
buffer = x
|
||||
case BufferProvider:
|
||||
buffer = x.Buffer()
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return buffer, true
|
||||
}
|
||||
|
||||
func (m *sayMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
buffer, ok := m.buffer(actual)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("Say must be passed a *gbytes.Buffer or BufferProvider. Got:\n%s", format.Object(actual, 1))
|
||||
}
|
||||
|
||||
didSay, sayings := buffer.didSay(m.re)
|
||||
m.receivedSayings = sayings
|
||||
|
||||
return didSay, nil
|
||||
}
|
||||
|
||||
func (m *sayMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return fmt.Sprintf(
|
||||
"Got stuck at:\n%s\nWaiting for:\n%s",
|
||||
format.IndentString(string(m.receivedSayings), 1),
|
||||
format.IndentString(m.re.String(), 1),
|
||||
)
|
||||
}
|
||||
|
||||
func (m *sayMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return fmt.Sprintf(
|
||||
"Saw:\n%s\nWhich matches the unexpected:\n%s",
|
||||
format.IndentString(string(m.receivedSayings), 1),
|
||||
format.IndentString(m.re.String(), 1),
|
||||
)
|
||||
}
|
||||
|
||||
func (m *sayMatcher) MatchMayChangeInTheFuture(actual interface{}) bool {
|
||||
switch x := actual.(type) {
|
||||
case *Buffer:
|
||||
return !x.Closed()
|
||||
case BufferProvider:
|
||||
return !x.Buffer().Closed()
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
112
vendor/github.com/onsi/gomega/gexec/build.go
generated
vendored
Normal file
112
vendor/github.com/onsi/gomega/gexec/build.go
generated
vendored
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
package gexec
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
mu sync.Mutex
|
||||
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. If $GOPATH is not set and you are using Go 1.8+,
|
||||
it will use the default GOPATH instead. It passes the variadic args on to `go build`.
|
||||
*/
|
||||
func Build(packagePath string, args ...string) (compiledPath string, err error) {
|
||||
return doBuild(build.Default.GOPATH, packagePath, nil, args...)
|
||||
}
|
||||
|
||||
/*
|
||||
BuildWithEnvironment is identical to Build but allows you to specify env vars to be set at build time.
|
||||
*/
|
||||
func BuildWithEnvironment(packagePath string, env []string, args ...string) (compiledPath string, err error) {
|
||||
return doBuild(build.Default.GOPATH, packagePath, env, 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) {
|
||||
return doBuild(gopath, packagePath, nil, args...)
|
||||
}
|
||||
|
||||
func replaceGoPath(environ []string, newGoPath string) []string {
|
||||
newEnviron := []string{}
|
||||
for _, v := range environ {
|
||||
if !strings.HasPrefix(v, "GOPATH=") {
|
||||
newEnviron = append(newEnviron, v)
|
||||
}
|
||||
}
|
||||
return append(newEnviron, "GOPATH="+newGoPath)
|
||||
}
|
||||
|
||||
func doBuild(gopath, packagePath string, env []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 = replaceGoPath(os.Environ(), gopath)
|
||||
build.Env = append(build.Env, env...)
|
||||
|
||||
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() {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if tmpDir != "" {
|
||||
os.RemoveAll(tmpDir)
|
||||
tmpDir = ""
|
||||
}
|
||||
}
|
||||
|
||||
func temporaryDirectory() (string, error) {
|
||||
var err error
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if tmpDir == "" {
|
||||
tmpDir, err = ioutil.TempDir("", "gexec_artifacts")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return ioutil.TempDir(tmpDir, "g")
|
||||
}
|
||||
86
vendor/github.com/onsi/gomega/gexec/exit_matcher.go
generated
vendored
Normal file
86
vendor/github.com/onsi/gomega/gexec/exit_matcher.go
generated
vendored
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
package gexec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
/*
|
||||
The Exit matcher operates on a session:
|
||||
|
||||
Expect(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."
|
||||
}
|
||||
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."
|
||||
}
|
||||
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
|
||||
}
|
||||
303
vendor/github.com/onsi/gomega/gexec/session.go
generated
vendored
Normal file
303
vendor/github.com/onsi/gomega/gexec/session.go
generated
vendored
Normal file
|
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
Package gexec provides support for testing external processes.
|
||||
*/
|
||||
package gexec
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"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:
|
||||
|
||||
Expect(session.Out).Should(gbytes.Say("foo-out"))
|
||||
Expect(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:
|
||||
|
||||
Expect(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:
|
||||
|
||||
Expect(session).Should(gexec.Exit())
|
||||
|
||||
When the session exits it closes the stdout and stderr gbytes buffers. This will short circuit any
|
||||
Eventuallys waiting for 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 {
|
||||
commandOut = io.MultiWriter(commandOut, outWriter)
|
||||
}
|
||||
|
||||
if errWriter != nil {
|
||||
commandErr = io.MultiWriter(commandErr, errWriter)
|
||||
}
|
||||
|
||||
command.Stdout = commandOut
|
||||
command.Stderr = commandErr
|
||||
|
||||
err := command.Start()
|
||||
if err == nil {
|
||||
go session.monitorForExit(exited)
|
||||
trackedSessionsMutex.Lock()
|
||||
defer trackedSessionsMutex.Unlock()
|
||||
trackedSessions = append(trackedSessions, session)
|
||||
}
|
||||
|
||||
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 {
|
||||
return s.Signal(syscall.SIGKILL)
|
||||
}
|
||||
|
||||
/*
|
||||
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)
|
||||
}
|
||||
|
||||
/*
|
||||
Signal 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.processIsAlive() {
|
||||
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)
|
||||
}
|
||||
|
||||
func (s *Session) processIsAlive() bool {
|
||||
return s.ExitCode() == -1 && s.Command.Process != nil
|
||||
}
|
||||
|
||||
var trackedSessions = []*Session{}
|
||||
var trackedSessionsMutex = &sync.Mutex{}
|
||||
|
||||
/*
|
||||
Kill sends a SIGKILL signal to all the processes started by Run, and waits for them to exit.
|
||||
The timeout specified is applied to each process killed.
|
||||
|
||||
If any of the processes already exited, KillAndWait returns silently.
|
||||
*/
|
||||
func KillAndWait(timeout ...interface{}) {
|
||||
trackedSessionsMutex.Lock()
|
||||
defer trackedSessionsMutex.Unlock()
|
||||
for _, session := range trackedSessions {
|
||||
session.Kill().Wait(timeout...)
|
||||
}
|
||||
trackedSessions = []*Session{}
|
||||
}
|
||||
|
||||
/*
|
||||
Kill sends a SIGTERM signal to all the processes started by Run, and waits for them to exit.
|
||||
The timeout specified is applied to each process killed.
|
||||
|
||||
If any of the processes already exited, TerminateAndWait returns silently.
|
||||
*/
|
||||
func TerminateAndWait(timeout ...interface{}) {
|
||||
trackedSessionsMutex.Lock()
|
||||
defer trackedSessionsMutex.Unlock()
|
||||
for _, session := range trackedSessions {
|
||||
session.Terminate().Wait(timeout...)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Kill sends a SIGKILL signal to all the processes started by Run.
|
||||
It does not wait for the processes to exit.
|
||||
|
||||
If any of the processes already exited, Kill returns silently.
|
||||
*/
|
||||
func Kill() {
|
||||
trackedSessionsMutex.Lock()
|
||||
defer trackedSessionsMutex.Unlock()
|
||||
for _, session := range trackedSessions {
|
||||
session.Kill()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Terminate sends a SIGTERM signal to all the processes started by Run.
|
||||
It does not wait for the processes to exit.
|
||||
|
||||
If any of the processes already exited, Terminate returns silently.
|
||||
*/
|
||||
func Terminate() {
|
||||
trackedSessionsMutex.Lock()
|
||||
defer trackedSessionsMutex.Unlock()
|
||||
for _, session := range trackedSessions {
|
||||
session.Terminate()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Signal sends the passed in signal to all the processes started by Run.
|
||||
It does not wait for the processes to exit.
|
||||
|
||||
If any of the processes already exited, Signal returns silently.
|
||||
*/
|
||||
func Signal(signal os.Signal) {
|
||||
trackedSessionsMutex.Lock()
|
||||
defer trackedSessionsMutex.Unlock()
|
||||
for _, session := range trackedSessions {
|
||||
session.Signal(signal)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Interrupt sends the SIGINT signal to all the processes started by Run.
|
||||
It does not wait for the processes to exit.
|
||||
|
||||
If any of the processes already exited, Interrupt returns silently.
|
||||
*/
|
||||
func Interrupt() {
|
||||
trackedSessionsMutex.Lock()
|
||||
defer trackedSessionsMutex.Unlock()
|
||||
for _, session := range trackedSessions {
|
||||
session.Interrupt()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue