mirror of
https://github.com/containrrr/watchtower.git
synced 2025-12-16 15:10:12 +01:00
Add godeps
This commit is contained in:
parent
c36d1dfffe
commit
ff277f9903
66 changed files with 10603 additions and 2073 deletions
32
Godeps/Godeps.json
generated
32
Godeps/Godeps.json
generated
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/CenturyLinkLabs/watchtower",
|
"ImportPath": "github.com/CenturyLinkLabs/watchtower",
|
||||||
"GoVersion": "go1.4.2",
|
"GoVersion": "go1.5",
|
||||||
"Packages": [
|
"Packages": [
|
||||||
"./..."
|
"./..."
|
||||||
],
|
],
|
||||||
|
|
@ -16,27 +16,39 @@
|
||||||
"Rev": "bca61c476e3c752594983e4c9bcd5f62fb09f157"
|
"Rev": "bca61c476e3c752594983e4c9bcd5f62fb09f157"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/docker/docker/pkg/units",
|
"ImportPath": "github.com/davecgh/go-spew/spew",
|
||||||
"Comment": "v1.4.1-4520-g469e234",
|
"Rev": "5215b55f46b2b919f50a1df0eaa5886afe4e3b3d"
|
||||||
"Rev": "469e234dedd84c13eea6271a8c6cc804e46cf22b"
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/docker/go-units",
|
||||||
|
"Comment": "v0.3.0",
|
||||||
|
"Rev": "5d2041e26a699eaca682e2ea41c8f891e1060444"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/pmezard/go-difflib/difflib",
|
||||||
|
"Rev": "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/samalba/dockerclient",
|
"ImportPath": "github.com/samalba/dockerclient",
|
||||||
"Rev": "15ebe064ca62ad0d64834e7ef0d4ed8ce9d02cde"
|
"Rev": "f274bbd0e2eb35ad1444dc6e6660214f9fbbc08c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/samalba/dockerclient/mockclient",
|
||||||
|
"Rev": "f274bbd0e2eb35ad1444dc6e6660214f9fbbc08c"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/stretchr/objx",
|
"ImportPath": "github.com/stretchr/objx",
|
||||||
"Rev": "cbeaeb16a013161a98496fad62933b1d21786672"
|
"Rev": "1a9d0bb9f541897e62256577b352fdbc1fb4fd94"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/stretchr/testify/assert",
|
"ImportPath": "github.com/stretchr/testify/assert",
|
||||||
"Comment": "v1.0-17-g089c718",
|
"Comment": "v1.1.3-6-g6fe211e",
|
||||||
"Rev": "089c7181b8c728499929ff09b62d3fdd8df8adff"
|
"Rev": "6fe211e493929a8aac0469b93f28b1d0688a9a3a"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/stretchr/testify/mock",
|
"ImportPath": "github.com/stretchr/testify/mock",
|
||||||
"Comment": "v1.0-17-g089c718",
|
"Comment": "v1.1.3-6-g6fe211e",
|
||||||
"Rev": "089c7181b8c728499929ff09b62d3fdd8df8adff"
|
"Rev": "6fe211e493929a8aac0469b93f28b1d0688a9a3a"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
Godeps/_workspace/src/github.com/davecgh/go-spew/LICENSE
generated
vendored
Normal file
13
Godeps/_workspace/src/github.com/davecgh/go-spew/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
Copyright (c) 2012-2013 Dave Collins <dave@davec.name>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
151
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
Normal file
151
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/bypass.go
generated
vendored
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
// Copyright (c) 2015 Dave Collins <dave@davec.name>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||||
|
// when the code is not running on Google App Engine and "-tags disableunsafe"
|
||||||
|
// is not added to the go build command line.
|
||||||
|
// +build !appengine,!disableunsafe
|
||||||
|
|
||||||
|
package spew
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// UnsafeDisabled is a build-time constant which specifies whether or
|
||||||
|
// not access to the unsafe package is available.
|
||||||
|
UnsafeDisabled = false
|
||||||
|
|
||||||
|
// ptrSize is the size of a pointer on the current arch.
|
||||||
|
ptrSize = unsafe.Sizeof((*byte)(nil))
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// offsetPtr, offsetScalar, and offsetFlag are the offsets for the
|
||||||
|
// internal reflect.Value fields. These values are valid before golang
|
||||||
|
// commit ecccf07e7f9d which changed the format. The are also valid
|
||||||
|
// after commit 82f48826c6c7 which changed the format again to mirror
|
||||||
|
// the original format. Code in the init function updates these offsets
|
||||||
|
// as necessary.
|
||||||
|
offsetPtr = uintptr(ptrSize)
|
||||||
|
offsetScalar = uintptr(0)
|
||||||
|
offsetFlag = uintptr(ptrSize * 2)
|
||||||
|
|
||||||
|
// flagKindWidth and flagKindShift indicate various bits that the
|
||||||
|
// reflect package uses internally to track kind information.
|
||||||
|
//
|
||||||
|
// flagRO indicates whether or not the value field of a reflect.Value is
|
||||||
|
// read-only.
|
||||||
|
//
|
||||||
|
// flagIndir indicates whether the value field of a reflect.Value is
|
||||||
|
// the actual data or a pointer to the data.
|
||||||
|
//
|
||||||
|
// These values are valid before golang commit 90a7c3c86944 which
|
||||||
|
// changed their positions. Code in the init function updates these
|
||||||
|
// flags as necessary.
|
||||||
|
flagKindWidth = uintptr(5)
|
||||||
|
flagKindShift = uintptr(flagKindWidth - 1)
|
||||||
|
flagRO = uintptr(1 << 0)
|
||||||
|
flagIndir = uintptr(1 << 1)
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Older versions of reflect.Value stored small integers directly in the
|
||||||
|
// ptr field (which is named val in the older versions). Versions
|
||||||
|
// between commits ecccf07e7f9d and 82f48826c6c7 added a new field named
|
||||||
|
// scalar for this purpose which unfortunately came before the flag
|
||||||
|
// field, so the offset of the flag field is different for those
|
||||||
|
// versions.
|
||||||
|
//
|
||||||
|
// This code constructs a new reflect.Value from a known small integer
|
||||||
|
// and checks if the size of the reflect.Value struct indicates it has
|
||||||
|
// the scalar field. When it does, the offsets are updated accordingly.
|
||||||
|
vv := reflect.ValueOf(0xf00)
|
||||||
|
if unsafe.Sizeof(vv) == (ptrSize * 4) {
|
||||||
|
offsetScalar = ptrSize * 2
|
||||||
|
offsetFlag = ptrSize * 3
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commit 90a7c3c86944 changed the flag positions such that the low
|
||||||
|
// order bits are the kind. This code extracts the kind from the flags
|
||||||
|
// field and ensures it's the correct type. When it's not, the flag
|
||||||
|
// order has been changed to the newer format, so the flags are updated
|
||||||
|
// accordingly.
|
||||||
|
upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag)
|
||||||
|
upfv := *(*uintptr)(upf)
|
||||||
|
flagKindMask := uintptr((1<<flagKindWidth - 1) << flagKindShift)
|
||||||
|
if (upfv&flagKindMask)>>flagKindShift != uintptr(reflect.Int) {
|
||||||
|
flagKindShift = 0
|
||||||
|
flagRO = 1 << 5
|
||||||
|
flagIndir = 1 << 6
|
||||||
|
|
||||||
|
// Commit adf9b30e5594 modified the flags to separate the
|
||||||
|
// flagRO flag into two bits which specifies whether or not the
|
||||||
|
// field is embedded. This causes flagIndir to move over a bit
|
||||||
|
// and means that flagRO is the combination of either of the
|
||||||
|
// original flagRO bit and the new bit.
|
||||||
|
//
|
||||||
|
// This code detects the change by extracting what used to be
|
||||||
|
// the indirect bit to ensure it's set. When it's not, the flag
|
||||||
|
// order has been changed to the newer format, so the flags are
|
||||||
|
// updated accordingly.
|
||||||
|
if upfv&flagIndir == 0 {
|
||||||
|
flagRO = 3 << 5
|
||||||
|
flagIndir = 1 << 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
|
||||||
|
// the typical safety restrictions preventing access to unaddressable and
|
||||||
|
// unexported data. It works by digging the raw pointer to the underlying
|
||||||
|
// value out of the protected value and generating a new unprotected (unsafe)
|
||||||
|
// reflect.Value to it.
|
||||||
|
//
|
||||||
|
// This allows us to check for implementations of the Stringer and error
|
||||||
|
// interfaces to be used for pretty printing ordinarily unaddressable and
|
||||||
|
// inaccessible values such as unexported struct fields.
|
||||||
|
func unsafeReflectValue(v reflect.Value) (rv reflect.Value) {
|
||||||
|
indirects := 1
|
||||||
|
vt := v.Type()
|
||||||
|
upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr)
|
||||||
|
rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag))
|
||||||
|
if rvf&flagIndir != 0 {
|
||||||
|
vt = reflect.PtrTo(v.Type())
|
||||||
|
indirects++
|
||||||
|
} else if offsetScalar != 0 {
|
||||||
|
// The value is in the scalar field when it's not one of the
|
||||||
|
// reference types.
|
||||||
|
switch vt.Kind() {
|
||||||
|
case reflect.Uintptr:
|
||||||
|
case reflect.Chan:
|
||||||
|
case reflect.Func:
|
||||||
|
case reflect.Map:
|
||||||
|
case reflect.Ptr:
|
||||||
|
case reflect.UnsafePointer:
|
||||||
|
default:
|
||||||
|
upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) +
|
||||||
|
offsetScalar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pv := reflect.NewAt(vt, upv)
|
||||||
|
rv = pv
|
||||||
|
for i := 0; i < indirects; i++ {
|
||||||
|
rv = rv.Elem()
|
||||||
|
}
|
||||||
|
return rv
|
||||||
|
}
|
||||||
37
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
Normal file
37
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/bypasssafe.go
generated
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright (c) 2015 Dave Collins <dave@davec.name>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||||
|
// when either the code is running on Google App Engine or "-tags disableunsafe"
|
||||||
|
// is added to the go build command line.
|
||||||
|
// +build appengine disableunsafe
|
||||||
|
|
||||||
|
package spew
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
|
const (
|
||||||
|
// UnsafeDisabled is a build-time constant which specifies whether or
|
||||||
|
// not access to the unsafe package is available.
|
||||||
|
UnsafeDisabled = true
|
||||||
|
)
|
||||||
|
|
||||||
|
// unsafeReflectValue typically converts the passed reflect.Value into a one
|
||||||
|
// that bypasses the typical safety restrictions preventing access to
|
||||||
|
// unaddressable and unexported data. However, doing this relies on access to
|
||||||
|
// the unsafe package. This is a stub version which simply returns the passed
|
||||||
|
// reflect.Value when the unsafe package is not available.
|
||||||
|
func unsafeReflectValue(v reflect.Value) reflect.Value {
|
||||||
|
return v
|
||||||
|
}
|
||||||
341
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common.go
generated
vendored
Normal file
341
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common.go
generated
vendored
Normal file
|
|
@ -0,0 +1,341 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package spew
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Some constants in the form of bytes to avoid string overhead. This mirrors
|
||||||
|
// the technique used in the fmt package.
|
||||||
|
var (
|
||||||
|
panicBytes = []byte("(PANIC=")
|
||||||
|
plusBytes = []byte("+")
|
||||||
|
iBytes = []byte("i")
|
||||||
|
trueBytes = []byte("true")
|
||||||
|
falseBytes = []byte("false")
|
||||||
|
interfaceBytes = []byte("(interface {})")
|
||||||
|
commaNewlineBytes = []byte(",\n")
|
||||||
|
newlineBytes = []byte("\n")
|
||||||
|
openBraceBytes = []byte("{")
|
||||||
|
openBraceNewlineBytes = []byte("{\n")
|
||||||
|
closeBraceBytes = []byte("}")
|
||||||
|
asteriskBytes = []byte("*")
|
||||||
|
colonBytes = []byte(":")
|
||||||
|
colonSpaceBytes = []byte(": ")
|
||||||
|
openParenBytes = []byte("(")
|
||||||
|
closeParenBytes = []byte(")")
|
||||||
|
spaceBytes = []byte(" ")
|
||||||
|
pointerChainBytes = []byte("->")
|
||||||
|
nilAngleBytes = []byte("<nil>")
|
||||||
|
maxNewlineBytes = []byte("<max depth reached>\n")
|
||||||
|
maxShortBytes = []byte("<max>")
|
||||||
|
circularBytes = []byte("<already shown>")
|
||||||
|
circularShortBytes = []byte("<shown>")
|
||||||
|
invalidAngleBytes = []byte("<invalid>")
|
||||||
|
openBracketBytes = []byte("[")
|
||||||
|
closeBracketBytes = []byte("]")
|
||||||
|
percentBytes = []byte("%")
|
||||||
|
precisionBytes = []byte(".")
|
||||||
|
openAngleBytes = []byte("<")
|
||||||
|
closeAngleBytes = []byte(">")
|
||||||
|
openMapBytes = []byte("map[")
|
||||||
|
closeMapBytes = []byte("]")
|
||||||
|
lenEqualsBytes = []byte("len=")
|
||||||
|
capEqualsBytes = []byte("cap=")
|
||||||
|
)
|
||||||
|
|
||||||
|
// hexDigits is used to map a decimal value to a hex digit.
|
||||||
|
var hexDigits = "0123456789abcdef"
|
||||||
|
|
||||||
|
// catchPanic handles any panics that might occur during the handleMethods
|
||||||
|
// calls.
|
||||||
|
func catchPanic(w io.Writer, v reflect.Value) {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
w.Write(panicBytes)
|
||||||
|
fmt.Fprintf(w, "%v", err)
|
||||||
|
w.Write(closeParenBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handleMethods attempts to call the Error and String methods on the underlying
|
||||||
|
// type the passed reflect.Value represents and outputes the result to Writer w.
|
||||||
|
//
|
||||||
|
// It handles panics in any called methods by catching and displaying the error
|
||||||
|
// as the formatted value.
|
||||||
|
func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
|
||||||
|
// We need an interface to check if the type implements the error or
|
||||||
|
// Stringer interface. However, the reflect package won't give us an
|
||||||
|
// interface on certain things like unexported struct fields in order
|
||||||
|
// to enforce visibility rules. We use unsafe, when it's available,
|
||||||
|
// to bypass these restrictions since this package does not mutate the
|
||||||
|
// values.
|
||||||
|
if !v.CanInterface() {
|
||||||
|
if UnsafeDisabled {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
v = unsafeReflectValue(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose whether or not to do error and Stringer interface lookups against
|
||||||
|
// the base type or a pointer to the base type depending on settings.
|
||||||
|
// Technically calling one of these methods with a pointer receiver can
|
||||||
|
// mutate the value, however, types which choose to satisify an error or
|
||||||
|
// Stringer interface with a pointer receiver should not be mutating their
|
||||||
|
// state inside these interface methods.
|
||||||
|
if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
|
||||||
|
v = unsafeReflectValue(v)
|
||||||
|
}
|
||||||
|
if v.CanAddr() {
|
||||||
|
v = v.Addr()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is it an error or Stringer?
|
||||||
|
switch iface := v.Interface().(type) {
|
||||||
|
case error:
|
||||||
|
defer catchPanic(w, v)
|
||||||
|
if cs.ContinueOnMethod {
|
||||||
|
w.Write(openParenBytes)
|
||||||
|
w.Write([]byte(iface.Error()))
|
||||||
|
w.Write(closeParenBytes)
|
||||||
|
w.Write(spaceBytes)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Write([]byte(iface.Error()))
|
||||||
|
return true
|
||||||
|
|
||||||
|
case fmt.Stringer:
|
||||||
|
defer catchPanic(w, v)
|
||||||
|
if cs.ContinueOnMethod {
|
||||||
|
w.Write(openParenBytes)
|
||||||
|
w.Write([]byte(iface.String()))
|
||||||
|
w.Write(closeParenBytes)
|
||||||
|
w.Write(spaceBytes)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
w.Write([]byte(iface.String()))
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// printBool outputs a boolean value as true or false to Writer w.
|
||||||
|
func printBool(w io.Writer, val bool) {
|
||||||
|
if val {
|
||||||
|
w.Write(trueBytes)
|
||||||
|
} else {
|
||||||
|
w.Write(falseBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// printInt outputs a signed integer value to Writer w.
|
||||||
|
func printInt(w io.Writer, val int64, base int) {
|
||||||
|
w.Write([]byte(strconv.FormatInt(val, base)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// printUint outputs an unsigned integer value to Writer w.
|
||||||
|
func printUint(w io.Writer, val uint64, base int) {
|
||||||
|
w.Write([]byte(strconv.FormatUint(val, base)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// printFloat outputs a floating point value using the specified precision,
|
||||||
|
// which is expected to be 32 or 64bit, to Writer w.
|
||||||
|
func printFloat(w io.Writer, val float64, precision int) {
|
||||||
|
w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// printComplex outputs a complex value using the specified float precision
|
||||||
|
// for the real and imaginary parts to Writer w.
|
||||||
|
func printComplex(w io.Writer, c complex128, floatPrecision int) {
|
||||||
|
r := real(c)
|
||||||
|
w.Write(openParenBytes)
|
||||||
|
w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
|
||||||
|
i := imag(c)
|
||||||
|
if i >= 0 {
|
||||||
|
w.Write(plusBytes)
|
||||||
|
}
|
||||||
|
w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
|
||||||
|
w.Write(iBytes)
|
||||||
|
w.Write(closeParenBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x'
|
||||||
|
// prefix to Writer w.
|
||||||
|
func printHexPtr(w io.Writer, p uintptr) {
|
||||||
|
// Null pointer.
|
||||||
|
num := uint64(p)
|
||||||
|
if num == 0 {
|
||||||
|
w.Write(nilAngleBytes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
|
||||||
|
buf := make([]byte, 18)
|
||||||
|
|
||||||
|
// It's simpler to construct the hex string right to left.
|
||||||
|
base := uint64(16)
|
||||||
|
i := len(buf) - 1
|
||||||
|
for num >= base {
|
||||||
|
buf[i] = hexDigits[num%base]
|
||||||
|
num /= base
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
buf[i] = hexDigits[num]
|
||||||
|
|
||||||
|
// Add '0x' prefix.
|
||||||
|
i--
|
||||||
|
buf[i] = 'x'
|
||||||
|
i--
|
||||||
|
buf[i] = '0'
|
||||||
|
|
||||||
|
// Strip unused leading bytes.
|
||||||
|
buf = buf[i:]
|
||||||
|
w.Write(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
// valuesSorter implements sort.Interface to allow a slice of reflect.Value
|
||||||
|
// elements to be sorted.
|
||||||
|
type valuesSorter struct {
|
||||||
|
values []reflect.Value
|
||||||
|
strings []string // either nil or same len and values
|
||||||
|
cs *ConfigState
|
||||||
|
}
|
||||||
|
|
||||||
|
// newValuesSorter initializes a valuesSorter instance, which holds a set of
|
||||||
|
// surrogate keys on which the data should be sorted. It uses flags in
|
||||||
|
// ConfigState to decide if and how to populate those surrogate keys.
|
||||||
|
func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
|
||||||
|
vs := &valuesSorter{values: values, cs: cs}
|
||||||
|
if canSortSimply(vs.values[0].Kind()) {
|
||||||
|
return vs
|
||||||
|
}
|
||||||
|
if !cs.DisableMethods {
|
||||||
|
vs.strings = make([]string, len(values))
|
||||||
|
for i := range vs.values {
|
||||||
|
b := bytes.Buffer{}
|
||||||
|
if !handleMethods(cs, &b, vs.values[i]) {
|
||||||
|
vs.strings = nil
|
||||||
|
break
|
||||||
|
}
|
||||||
|
vs.strings[i] = b.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if vs.strings == nil && cs.SpewKeys {
|
||||||
|
vs.strings = make([]string, len(values))
|
||||||
|
for i := range vs.values {
|
||||||
|
vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vs
|
||||||
|
}
|
||||||
|
|
||||||
|
// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
|
||||||
|
// directly, or whether it should be considered for sorting by surrogate keys
|
||||||
|
// (if the ConfigState allows it).
|
||||||
|
func canSortSimply(kind reflect.Kind) bool {
|
||||||
|
// This switch parallels valueSortLess, except for the default case.
|
||||||
|
switch kind {
|
||||||
|
case reflect.Bool:
|
||||||
|
return true
|
||||||
|
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||||
|
return true
|
||||||
|
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||||
|
return true
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return true
|
||||||
|
case reflect.String:
|
||||||
|
return true
|
||||||
|
case reflect.Uintptr:
|
||||||
|
return true
|
||||||
|
case reflect.Array:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of values in the slice. It is part of the
|
||||||
|
// sort.Interface implementation.
|
||||||
|
func (s *valuesSorter) Len() int {
|
||||||
|
return len(s.values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap swaps the values at the passed indices. It is part of the
|
||||||
|
// sort.Interface implementation.
|
||||||
|
func (s *valuesSorter) Swap(i, j int) {
|
||||||
|
s.values[i], s.values[j] = s.values[j], s.values[i]
|
||||||
|
if s.strings != nil {
|
||||||
|
s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// valueSortLess returns whether the first value should sort before the second
|
||||||
|
// value. It is used by valueSorter.Less as part of the sort.Interface
|
||||||
|
// implementation.
|
||||||
|
func valueSortLess(a, b reflect.Value) bool {
|
||||||
|
switch a.Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
return !a.Bool() && b.Bool()
|
||||||
|
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||||
|
return a.Int() < b.Int()
|
||||||
|
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||||
|
return a.Uint() < b.Uint()
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return a.Float() < b.Float()
|
||||||
|
case reflect.String:
|
||||||
|
return a.String() < b.String()
|
||||||
|
case reflect.Uintptr:
|
||||||
|
return a.Uint() < b.Uint()
|
||||||
|
case reflect.Array:
|
||||||
|
// Compare the contents of both arrays.
|
||||||
|
l := a.Len()
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
av := a.Index(i)
|
||||||
|
bv := b.Index(i)
|
||||||
|
if av.Interface() == bv.Interface() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return valueSortLess(av, bv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a.String() < b.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less returns whether the value at index i should sort before the
|
||||||
|
// value at index j. It is part of the sort.Interface implementation.
|
||||||
|
func (s *valuesSorter) Less(i, j int) bool {
|
||||||
|
if s.strings == nil {
|
||||||
|
return valueSortLess(s.values[i], s.values[j])
|
||||||
|
}
|
||||||
|
return s.strings[i] < s.strings[j]
|
||||||
|
}
|
||||||
|
|
||||||
|
// sortValues is a sort function that handles both native types and any type that
|
||||||
|
// can be converted to error or Stringer. Other inputs are sorted according to
|
||||||
|
// their Value.String() value to ensure display stability.
|
||||||
|
func sortValues(values []reflect.Value, cs *ConfigState) {
|
||||||
|
if len(values) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
sort.Sort(newValuesSorter(values, cs))
|
||||||
|
}
|
||||||
298
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common_test.go
generated
vendored
Normal file
298
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,298 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package spew_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
)
|
||||||
|
|
||||||
|
// custom type to test Stinger interface on non-pointer receiver.
|
||||||
|
type stringer string
|
||||||
|
|
||||||
|
// String implements the Stringer interface for testing invocation of custom
|
||||||
|
// stringers on types with non-pointer receivers.
|
||||||
|
func (s stringer) String() string {
|
||||||
|
return "stringer " + string(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom type to test Stinger interface on pointer receiver.
|
||||||
|
type pstringer string
|
||||||
|
|
||||||
|
// String implements the Stringer interface for testing invocation of custom
|
||||||
|
// stringers on types with only pointer receivers.
|
||||||
|
func (s *pstringer) String() string {
|
||||||
|
return "stringer " + string(*s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// xref1 and xref2 are cross referencing structs for testing circular reference
|
||||||
|
// detection.
|
||||||
|
type xref1 struct {
|
||||||
|
ps2 *xref2
|
||||||
|
}
|
||||||
|
type xref2 struct {
|
||||||
|
ps1 *xref1
|
||||||
|
}
|
||||||
|
|
||||||
|
// indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular
|
||||||
|
// reference for testing detection.
|
||||||
|
type indirCir1 struct {
|
||||||
|
ps2 *indirCir2
|
||||||
|
}
|
||||||
|
type indirCir2 struct {
|
||||||
|
ps3 *indirCir3
|
||||||
|
}
|
||||||
|
type indirCir3 struct {
|
||||||
|
ps1 *indirCir1
|
||||||
|
}
|
||||||
|
|
||||||
|
// embed is used to test embedded structures.
|
||||||
|
type embed struct {
|
||||||
|
a string
|
||||||
|
}
|
||||||
|
|
||||||
|
// embedwrap is used to test embedded structures.
|
||||||
|
type embedwrap struct {
|
||||||
|
*embed
|
||||||
|
e *embed
|
||||||
|
}
|
||||||
|
|
||||||
|
// panicer is used to intentionally cause a panic for testing spew properly
|
||||||
|
// handles them
|
||||||
|
type panicer int
|
||||||
|
|
||||||
|
func (p panicer) String() string {
|
||||||
|
panic("test panic")
|
||||||
|
}
|
||||||
|
|
||||||
|
// customError is used to test custom error interface invocation.
|
||||||
|
type customError int
|
||||||
|
|
||||||
|
func (e customError) Error() string {
|
||||||
|
return fmt.Sprintf("error: %d", int(e))
|
||||||
|
}
|
||||||
|
|
||||||
|
// stringizeWants converts a slice of wanted test output into a format suitable
|
||||||
|
// for a test error message.
|
||||||
|
func stringizeWants(wants []string) string {
|
||||||
|
s := ""
|
||||||
|
for i, want := range wants {
|
||||||
|
if i > 0 {
|
||||||
|
s += fmt.Sprintf("want%d: %s", i+1, want)
|
||||||
|
} else {
|
||||||
|
s += "want: " + want
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFailed returns whether or not a test failed by checking if the result
|
||||||
|
// of the test is in the slice of wanted strings.
|
||||||
|
func testFailed(result string, wants []string) bool {
|
||||||
|
for _, want := range wants {
|
||||||
|
if result == want {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
type sortableStruct struct {
|
||||||
|
x int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ss sortableStruct) String() string {
|
||||||
|
return fmt.Sprintf("ss.%d", ss.x)
|
||||||
|
}
|
||||||
|
|
||||||
|
type unsortableStruct struct {
|
||||||
|
x int
|
||||||
|
}
|
||||||
|
|
||||||
|
type sortTestCase struct {
|
||||||
|
input []reflect.Value
|
||||||
|
expected []reflect.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func helpTestSortValues(tests []sortTestCase, cs *spew.ConfigState, t *testing.T) {
|
||||||
|
getInterfaces := func(values []reflect.Value) []interface{} {
|
||||||
|
interfaces := []interface{}{}
|
||||||
|
for _, v := range values {
|
||||||
|
interfaces = append(interfaces, v.Interface())
|
||||||
|
}
|
||||||
|
return interfaces
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
spew.SortValues(test.input, cs)
|
||||||
|
// reflect.DeepEqual cannot really make sense of reflect.Value,
|
||||||
|
// probably because of all the pointer tricks. For instance,
|
||||||
|
// v(2.0) != v(2.0) on a 32-bits system. Turn them into interface{}
|
||||||
|
// instead.
|
||||||
|
input := getInterfaces(test.input)
|
||||||
|
expected := getInterfaces(test.expected)
|
||||||
|
if !reflect.DeepEqual(input, expected) {
|
||||||
|
t.Errorf("Sort mismatch:\n %v != %v", input, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestSortValues ensures the sort functionality for relect.Value based sorting
|
||||||
|
// works as intended.
|
||||||
|
func TestSortValues(t *testing.T) {
|
||||||
|
v := reflect.ValueOf
|
||||||
|
|
||||||
|
a := v("a")
|
||||||
|
b := v("b")
|
||||||
|
c := v("c")
|
||||||
|
embedA := v(embed{"a"})
|
||||||
|
embedB := v(embed{"b"})
|
||||||
|
embedC := v(embed{"c"})
|
||||||
|
tests := []sortTestCase{
|
||||||
|
// No values.
|
||||||
|
{
|
||||||
|
[]reflect.Value{},
|
||||||
|
[]reflect.Value{},
|
||||||
|
},
|
||||||
|
// Bools.
|
||||||
|
{
|
||||||
|
[]reflect.Value{v(false), v(true), v(false)},
|
||||||
|
[]reflect.Value{v(false), v(false), v(true)},
|
||||||
|
},
|
||||||
|
// Ints.
|
||||||
|
{
|
||||||
|
[]reflect.Value{v(2), v(1), v(3)},
|
||||||
|
[]reflect.Value{v(1), v(2), v(3)},
|
||||||
|
},
|
||||||
|
// Uints.
|
||||||
|
{
|
||||||
|
[]reflect.Value{v(uint8(2)), v(uint8(1)), v(uint8(3))},
|
||||||
|
[]reflect.Value{v(uint8(1)), v(uint8(2)), v(uint8(3))},
|
||||||
|
},
|
||||||
|
// Floats.
|
||||||
|
{
|
||||||
|
[]reflect.Value{v(2.0), v(1.0), v(3.0)},
|
||||||
|
[]reflect.Value{v(1.0), v(2.0), v(3.0)},
|
||||||
|
},
|
||||||
|
// Strings.
|
||||||
|
{
|
||||||
|
[]reflect.Value{b, a, c},
|
||||||
|
[]reflect.Value{a, b, c},
|
||||||
|
},
|
||||||
|
// Array
|
||||||
|
{
|
||||||
|
[]reflect.Value{v([3]int{3, 2, 1}), v([3]int{1, 3, 2}), v([3]int{1, 2, 3})},
|
||||||
|
[]reflect.Value{v([3]int{1, 2, 3}), v([3]int{1, 3, 2}), v([3]int{3, 2, 1})},
|
||||||
|
},
|
||||||
|
// Uintptrs.
|
||||||
|
{
|
||||||
|
[]reflect.Value{v(uintptr(2)), v(uintptr(1)), v(uintptr(3))},
|
||||||
|
[]reflect.Value{v(uintptr(1)), v(uintptr(2)), v(uintptr(3))},
|
||||||
|
},
|
||||||
|
// SortableStructs.
|
||||||
|
{
|
||||||
|
// Note: not sorted - DisableMethods is set.
|
||||||
|
[]reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
|
||||||
|
[]reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
|
||||||
|
},
|
||||||
|
// UnsortableStructs.
|
||||||
|
{
|
||||||
|
// Note: not sorted - SpewKeys is false.
|
||||||
|
[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
|
||||||
|
[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
|
||||||
|
},
|
||||||
|
// Invalid.
|
||||||
|
{
|
||||||
|
[]reflect.Value{embedB, embedA, embedC},
|
||||||
|
[]reflect.Value{embedB, embedA, embedC},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cs := spew.ConfigState{DisableMethods: true, SpewKeys: false}
|
||||||
|
helpTestSortValues(tests, &cs, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestSortValuesWithMethods ensures the sort functionality for relect.Value
|
||||||
|
// based sorting works as intended when using string methods.
|
||||||
|
func TestSortValuesWithMethods(t *testing.T) {
|
||||||
|
v := reflect.ValueOf
|
||||||
|
|
||||||
|
a := v("a")
|
||||||
|
b := v("b")
|
||||||
|
c := v("c")
|
||||||
|
tests := []sortTestCase{
|
||||||
|
// Ints.
|
||||||
|
{
|
||||||
|
[]reflect.Value{v(2), v(1), v(3)},
|
||||||
|
[]reflect.Value{v(1), v(2), v(3)},
|
||||||
|
},
|
||||||
|
// Strings.
|
||||||
|
{
|
||||||
|
[]reflect.Value{b, a, c},
|
||||||
|
[]reflect.Value{a, b, c},
|
||||||
|
},
|
||||||
|
// SortableStructs.
|
||||||
|
{
|
||||||
|
[]reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
|
||||||
|
[]reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})},
|
||||||
|
},
|
||||||
|
// UnsortableStructs.
|
||||||
|
{
|
||||||
|
// Note: not sorted - SpewKeys is false.
|
||||||
|
[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
|
||||||
|
[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cs := spew.ConfigState{DisableMethods: false, SpewKeys: false}
|
||||||
|
helpTestSortValues(tests, &cs, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestSortValuesWithSpew ensures the sort functionality for relect.Value
|
||||||
|
// based sorting works as intended when using spew to stringify keys.
|
||||||
|
func TestSortValuesWithSpew(t *testing.T) {
|
||||||
|
v := reflect.ValueOf
|
||||||
|
|
||||||
|
a := v("a")
|
||||||
|
b := v("b")
|
||||||
|
c := v("c")
|
||||||
|
tests := []sortTestCase{
|
||||||
|
// Ints.
|
||||||
|
{
|
||||||
|
[]reflect.Value{v(2), v(1), v(3)},
|
||||||
|
[]reflect.Value{v(1), v(2), v(3)},
|
||||||
|
},
|
||||||
|
// Strings.
|
||||||
|
{
|
||||||
|
[]reflect.Value{b, a, c},
|
||||||
|
[]reflect.Value{a, b, c},
|
||||||
|
},
|
||||||
|
// SortableStructs.
|
||||||
|
{
|
||||||
|
[]reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})},
|
||||||
|
[]reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})},
|
||||||
|
},
|
||||||
|
// UnsortableStructs.
|
||||||
|
{
|
||||||
|
[]reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})},
|
||||||
|
[]reflect.Value{v(unsortableStruct{1}), v(unsortableStruct{2}), v(unsortableStruct{3})},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cs := spew.ConfigState{DisableMethods: true, SpewKeys: true}
|
||||||
|
helpTestSortValues(tests, &cs, t)
|
||||||
|
}
|
||||||
297
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/config.go
generated
vendored
Normal file
297
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/config.go
generated
vendored
Normal file
|
|
@ -0,0 +1,297 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package spew
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ConfigState houses the configuration options used by spew to format and
|
||||||
|
// display values. There is a global instance, Config, that is used to control
|
||||||
|
// all top-level Formatter and Dump functionality. Each ConfigState instance
|
||||||
|
// provides methods equivalent to the top-level functions.
|
||||||
|
//
|
||||||
|
// The zero value for ConfigState provides no indentation. You would typically
|
||||||
|
// want to set it to a space or a tab.
|
||||||
|
//
|
||||||
|
// Alternatively, you can use NewDefaultConfig to get a ConfigState instance
|
||||||
|
// with default settings. See the documentation of NewDefaultConfig for default
|
||||||
|
// values.
|
||||||
|
type ConfigState struct {
|
||||||
|
// Indent specifies the string to use for each indentation level. The
|
||||||
|
// global config instance that all top-level functions use set this to a
|
||||||
|
// single space by default. If you would like more indentation, you might
|
||||||
|
// set this to a tab with "\t" or perhaps two spaces with " ".
|
||||||
|
Indent string
|
||||||
|
|
||||||
|
// MaxDepth controls the maximum number of levels to descend into nested
|
||||||
|
// data structures. The default, 0, means there is no limit.
|
||||||
|
//
|
||||||
|
// NOTE: Circular data structures are properly detected, so it is not
|
||||||
|
// necessary to set this value unless you specifically want to limit deeply
|
||||||
|
// nested data structures.
|
||||||
|
MaxDepth int
|
||||||
|
|
||||||
|
// DisableMethods specifies whether or not error and Stringer interfaces are
|
||||||
|
// invoked for types that implement them.
|
||||||
|
DisableMethods bool
|
||||||
|
|
||||||
|
// DisablePointerMethods specifies whether or not to check for and invoke
|
||||||
|
// error and Stringer interfaces on types which only accept a pointer
|
||||||
|
// receiver when the current type is not a pointer.
|
||||||
|
//
|
||||||
|
// NOTE: This might be an unsafe action since calling one of these methods
|
||||||
|
// with a pointer receiver could technically mutate the value, however,
|
||||||
|
// in practice, types which choose to satisify an error or Stringer
|
||||||
|
// interface with a pointer receiver should not be mutating their state
|
||||||
|
// inside these interface methods. As a result, this option relies on
|
||||||
|
// access to the unsafe package, so it will not have any effect when
|
||||||
|
// running in environments without access to the unsafe package such as
|
||||||
|
// Google App Engine or with the "disableunsafe" build tag specified.
|
||||||
|
DisablePointerMethods bool
|
||||||
|
|
||||||
|
// ContinueOnMethod specifies whether or not recursion should continue once
|
||||||
|
// a custom error or Stringer interface is invoked. The default, false,
|
||||||
|
// means it will print the results of invoking the custom error or Stringer
|
||||||
|
// interface and return immediately instead of continuing to recurse into
|
||||||
|
// the internals of the data type.
|
||||||
|
//
|
||||||
|
// NOTE: This flag does not have any effect if method invocation is disabled
|
||||||
|
// via the DisableMethods or DisablePointerMethods options.
|
||||||
|
ContinueOnMethod bool
|
||||||
|
|
||||||
|
// SortKeys specifies map keys should be sorted before being printed. Use
|
||||||
|
// this to have a more deterministic, diffable output. Note that only
|
||||||
|
// native types (bool, int, uint, floats, uintptr and string) and types
|
||||||
|
// that support the error or Stringer interfaces (if methods are
|
||||||
|
// enabled) are supported, with other types sorted according to the
|
||||||
|
// reflect.Value.String() output which guarantees display stability.
|
||||||
|
SortKeys bool
|
||||||
|
|
||||||
|
// SpewKeys specifies that, as a last resort attempt, map keys should
|
||||||
|
// be spewed to strings and sorted by those strings. This is only
|
||||||
|
// considered if SortKeys is true.
|
||||||
|
SpewKeys bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config is the active configuration of the top-level functions.
|
||||||
|
// The configuration can be changed by modifying the contents of spew.Config.
|
||||||
|
var Config = ConfigState{Indent: " "}
|
||||||
|
|
||||||
|
// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
|
||||||
|
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||||
|
// the formatted string as a value that satisfies error. See NewFormatter
|
||||||
|
// for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b))
|
||||||
|
func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) {
|
||||||
|
return fmt.Errorf(format, c.convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
|
||||||
|
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||||
|
// the number of bytes written and any write error encountered. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b))
|
||||||
|
func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
|
||||||
|
return fmt.Fprint(w, c.convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
|
||||||
|
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||||
|
// the number of bytes written and any write error encountered. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b))
|
||||||
|
func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
|
||||||
|
return fmt.Fprintf(w, format, c.convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
|
||||||
|
// passed with a Formatter interface returned by c.NewFormatter. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b))
|
||||||
|
func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
|
||||||
|
return fmt.Fprintln(w, c.convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print is a wrapper for fmt.Print that treats each argument as if it were
|
||||||
|
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||||
|
// the number of bytes written and any write error encountered. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Print(c.NewFormatter(a), c.NewFormatter(b))
|
||||||
|
func (c *ConfigState) Print(a ...interface{}) (n int, err error) {
|
||||||
|
return fmt.Print(c.convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printf is a wrapper for fmt.Printf that treats each argument as if it were
|
||||||
|
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||||
|
// the number of bytes written and any write error encountered. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b))
|
||||||
|
func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) {
|
||||||
|
return fmt.Printf(format, c.convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Println is a wrapper for fmt.Println that treats each argument as if it were
|
||||||
|
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||||
|
// the number of bytes written and any write error encountered. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Println(c.NewFormatter(a), c.NewFormatter(b))
|
||||||
|
func (c *ConfigState) Println(a ...interface{}) (n int, err error) {
|
||||||
|
return fmt.Println(c.convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
|
||||||
|
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||||
|
// the resulting string. See NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b))
|
||||||
|
func (c *ConfigState) Sprint(a ...interface{}) string {
|
||||||
|
return fmt.Sprint(c.convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
|
||||||
|
// passed with a Formatter interface returned by c.NewFormatter. It returns
|
||||||
|
// the resulting string. See NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b))
|
||||||
|
func (c *ConfigState) Sprintf(format string, a ...interface{}) string {
|
||||||
|
return fmt.Sprintf(format, c.convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
|
||||||
|
// were passed with a Formatter interface returned by c.NewFormatter. It
|
||||||
|
// returns the resulting string. See NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b))
|
||||||
|
func (c *ConfigState) Sprintln(a ...interface{}) string {
|
||||||
|
return fmt.Sprintln(c.convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
NewFormatter returns a custom formatter that satisfies the fmt.Formatter
|
||||||
|
interface. As a result, it integrates cleanly with standard fmt package
|
||||||
|
printing functions. The formatter is useful for inline printing of smaller data
|
||||||
|
types similar to the standard %v format specifier.
|
||||||
|
|
||||||
|
The custom formatter only responds to the %v (most compact), %+v (adds pointer
|
||||||
|
addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb
|
||||||
|
combinations. Any other verbs such as %x and %q will be sent to the the
|
||||||
|
standard fmt package for formatting. In addition, the custom formatter ignores
|
||||||
|
the width and precision arguments (however they will still work on the format
|
||||||
|
specifiers not handled by the custom formatter).
|
||||||
|
|
||||||
|
Typically this function shouldn't be called directly. It is much easier to make
|
||||||
|
use of the custom formatter by calling one of the convenience functions such as
|
||||||
|
c.Printf, c.Println, or c.Printf.
|
||||||
|
*/
|
||||||
|
func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter {
|
||||||
|
return newFormatter(c, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fdump formats and displays the passed arguments to io.Writer w. It formats
|
||||||
|
// exactly the same as Dump.
|
||||||
|
func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) {
|
||||||
|
fdump(c, w, a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Dump displays the passed parameters to standard out with newlines, customizable
|
||||||
|
indentation, and additional debug information such as complete types and all
|
||||||
|
pointer addresses used to indirect to the final value. It provides the
|
||||||
|
following features over the built-in printing facilities provided by the fmt
|
||||||
|
package:
|
||||||
|
|
||||||
|
* Pointers are dereferenced and followed
|
||||||
|
* Circular data structures are detected and handled properly
|
||||||
|
* Custom Stringer/error interfaces are optionally invoked, including
|
||||||
|
on unexported types
|
||||||
|
* Custom types which only implement the Stringer/error interfaces via
|
||||||
|
a pointer receiver are optionally invoked when passing non-pointer
|
||||||
|
variables
|
||||||
|
* Byte arrays and slices are dumped like the hexdump -C command which
|
||||||
|
includes offsets, byte values in hex, and ASCII output
|
||||||
|
|
||||||
|
The configuration options are controlled by modifying the public members
|
||||||
|
of c. See ConfigState for options documentation.
|
||||||
|
|
||||||
|
See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
|
||||||
|
get the formatted result as a string.
|
||||||
|
*/
|
||||||
|
func (c *ConfigState) Dump(a ...interface{}) {
|
||||||
|
fdump(c, os.Stdout, a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sdump returns a string with the passed arguments formatted exactly the same
|
||||||
|
// as Dump.
|
||||||
|
func (c *ConfigState) Sdump(a ...interface{}) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
fdump(c, &buf, a...)
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertArgs accepts a slice of arguments and returns a slice of the same
|
||||||
|
// length with each argument converted to a spew Formatter interface using
|
||||||
|
// the ConfigState associated with s.
|
||||||
|
func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) {
|
||||||
|
formatters = make([]interface{}, len(args))
|
||||||
|
for index, arg := range args {
|
||||||
|
formatters[index] = newFormatter(c, arg)
|
||||||
|
}
|
||||||
|
return formatters
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDefaultConfig returns a ConfigState with the following default settings.
|
||||||
|
//
|
||||||
|
// Indent: " "
|
||||||
|
// MaxDepth: 0
|
||||||
|
// DisableMethods: false
|
||||||
|
// DisablePointerMethods: false
|
||||||
|
// ContinueOnMethod: false
|
||||||
|
// SortKeys: false
|
||||||
|
func NewDefaultConfig() *ConfigState {
|
||||||
|
return &ConfigState{Indent: " "}
|
||||||
|
}
|
||||||
202
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/doc.go
generated
vendored
Normal file
202
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/doc.go
generated
vendored
Normal file
|
|
@ -0,0 +1,202 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Package spew implements a deep pretty printer for Go data structures to aid in
|
||||||
|
debugging.
|
||||||
|
|
||||||
|
A quick overview of the additional features spew provides over the built-in
|
||||||
|
printing facilities for Go data types are as follows:
|
||||||
|
|
||||||
|
* Pointers are dereferenced and followed
|
||||||
|
* Circular data structures are detected and handled properly
|
||||||
|
* Custom Stringer/error interfaces are optionally invoked, including
|
||||||
|
on unexported types
|
||||||
|
* Custom types which only implement the Stringer/error interfaces via
|
||||||
|
a pointer receiver are optionally invoked when passing non-pointer
|
||||||
|
variables
|
||||||
|
* Byte arrays and slices are dumped like the hexdump -C command which
|
||||||
|
includes offsets, byte values in hex, and ASCII output (only when using
|
||||||
|
Dump style)
|
||||||
|
|
||||||
|
There are two different approaches spew allows for dumping Go data structures:
|
||||||
|
|
||||||
|
* Dump style which prints with newlines, customizable indentation,
|
||||||
|
and additional debug information such as types and all pointer addresses
|
||||||
|
used to indirect to the final value
|
||||||
|
* A custom Formatter interface that integrates cleanly with the standard fmt
|
||||||
|
package and replaces %v, %+v, %#v, and %#+v to provide inline printing
|
||||||
|
similar to the default %v while providing the additional functionality
|
||||||
|
outlined above and passing unsupported format verbs such as %x and %q
|
||||||
|
along to fmt
|
||||||
|
|
||||||
|
Quick Start
|
||||||
|
|
||||||
|
This section demonstrates how to quickly get started with spew. See the
|
||||||
|
sections below for further details on formatting and configuration options.
|
||||||
|
|
||||||
|
To dump a variable with full newlines, indentation, type, and pointer
|
||||||
|
information use Dump, Fdump, or Sdump:
|
||||||
|
spew.Dump(myVar1, myVar2, ...)
|
||||||
|
spew.Fdump(someWriter, myVar1, myVar2, ...)
|
||||||
|
str := spew.Sdump(myVar1, myVar2, ...)
|
||||||
|
|
||||||
|
Alternatively, if you would prefer to use format strings with a compacted inline
|
||||||
|
printing style, use the convenience wrappers Printf, Fprintf, etc with
|
||||||
|
%v (most compact), %+v (adds pointer addresses), %#v (adds types), or
|
||||||
|
%#+v (adds types and pointer addresses):
|
||||||
|
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
||||||
|
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
||||||
|
spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
||||||
|
spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
||||||
|
|
||||||
|
Configuration Options
|
||||||
|
|
||||||
|
Configuration of spew is handled by fields in the ConfigState type. For
|
||||||
|
convenience, all of the top-level functions use a global state available
|
||||||
|
via the spew.Config global.
|
||||||
|
|
||||||
|
It is also possible to create a ConfigState instance that provides methods
|
||||||
|
equivalent to the top-level functions. This allows concurrent configuration
|
||||||
|
options. See the ConfigState documentation for more details.
|
||||||
|
|
||||||
|
The following configuration options are available:
|
||||||
|
* Indent
|
||||||
|
String to use for each indentation level for Dump functions.
|
||||||
|
It is a single space by default. A popular alternative is "\t".
|
||||||
|
|
||||||
|
* MaxDepth
|
||||||
|
Maximum number of levels to descend into nested data structures.
|
||||||
|
There is no limit by default.
|
||||||
|
|
||||||
|
* DisableMethods
|
||||||
|
Disables invocation of error and Stringer interface methods.
|
||||||
|
Method invocation is enabled by default.
|
||||||
|
|
||||||
|
* DisablePointerMethods
|
||||||
|
Disables invocation of error and Stringer interface methods on types
|
||||||
|
which only accept pointer receivers from non-pointer variables.
|
||||||
|
Pointer method invocation is enabled by default.
|
||||||
|
|
||||||
|
* ContinueOnMethod
|
||||||
|
Enables recursion into types after invoking error and Stringer interface
|
||||||
|
methods. Recursion after method invocation is disabled by default.
|
||||||
|
|
||||||
|
* SortKeys
|
||||||
|
Specifies map keys should be sorted before being printed. Use
|
||||||
|
this to have a more deterministic, diffable output. Note that
|
||||||
|
only native types (bool, int, uint, floats, uintptr and string)
|
||||||
|
and types which implement error or Stringer interfaces are
|
||||||
|
supported with other types sorted according to the
|
||||||
|
reflect.Value.String() output which guarantees display
|
||||||
|
stability. Natural map order is used by default.
|
||||||
|
|
||||||
|
* SpewKeys
|
||||||
|
Specifies that, as a last resort attempt, map keys should be
|
||||||
|
spewed to strings and sorted by those strings. This is only
|
||||||
|
considered if SortKeys is true.
|
||||||
|
|
||||||
|
Dump Usage
|
||||||
|
|
||||||
|
Simply call spew.Dump with a list of variables you want to dump:
|
||||||
|
|
||||||
|
spew.Dump(myVar1, myVar2, ...)
|
||||||
|
|
||||||
|
You may also call spew.Fdump if you would prefer to output to an arbitrary
|
||||||
|
io.Writer. For example, to dump to standard error:
|
||||||
|
|
||||||
|
spew.Fdump(os.Stderr, myVar1, myVar2, ...)
|
||||||
|
|
||||||
|
A third option is to call spew.Sdump to get the formatted output as a string:
|
||||||
|
|
||||||
|
str := spew.Sdump(myVar1, myVar2, ...)
|
||||||
|
|
||||||
|
Sample Dump Output
|
||||||
|
|
||||||
|
See the Dump example for details on the setup of the types and variables being
|
||||||
|
shown here.
|
||||||
|
|
||||||
|
(main.Foo) {
|
||||||
|
unexportedField: (*main.Bar)(0xf84002e210)({
|
||||||
|
flag: (main.Flag) flagTwo,
|
||||||
|
data: (uintptr) <nil>
|
||||||
|
}),
|
||||||
|
ExportedField: (map[interface {}]interface {}) (len=1) {
|
||||||
|
(string) (len=3) "one": (bool) true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C
|
||||||
|
command as shown.
|
||||||
|
([]uint8) (len=32 cap=32) {
|
||||||
|
00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
|
||||||
|
00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
|
||||||
|
00000020 31 32 |12|
|
||||||
|
}
|
||||||
|
|
||||||
|
Custom Formatter
|
||||||
|
|
||||||
|
Spew provides a custom formatter that implements the fmt.Formatter interface
|
||||||
|
so that it integrates cleanly with standard fmt package printing functions. The
|
||||||
|
formatter is useful for inline printing of smaller data types similar to the
|
||||||
|
standard %v format specifier.
|
||||||
|
|
||||||
|
The custom formatter only responds to the %v (most compact), %+v (adds pointer
|
||||||
|
addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
|
||||||
|
combinations. Any other verbs such as %x and %q will be sent to the the
|
||||||
|
standard fmt package for formatting. In addition, the custom formatter ignores
|
||||||
|
the width and precision arguments (however they will still work on the format
|
||||||
|
specifiers not handled by the custom formatter).
|
||||||
|
|
||||||
|
Custom Formatter Usage
|
||||||
|
|
||||||
|
The simplest way to make use of the spew custom formatter is to call one of the
|
||||||
|
convenience functions such as spew.Printf, spew.Println, or spew.Printf. The
|
||||||
|
functions have syntax you are most likely already familiar with:
|
||||||
|
|
||||||
|
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
||||||
|
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
||||||
|
spew.Println(myVar, myVar2)
|
||||||
|
spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
|
||||||
|
spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
|
||||||
|
|
||||||
|
See the Index for the full list convenience functions.
|
||||||
|
|
||||||
|
Sample Formatter Output
|
||||||
|
|
||||||
|
Double pointer to a uint8:
|
||||||
|
%v: <**>5
|
||||||
|
%+v: <**>(0xf8400420d0->0xf8400420c8)5
|
||||||
|
%#v: (**uint8)5
|
||||||
|
%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
|
||||||
|
|
||||||
|
Pointer to circular struct with a uint8 field and a pointer to itself:
|
||||||
|
%v: <*>{1 <*><shown>}
|
||||||
|
%+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
|
||||||
|
%#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
|
||||||
|
%#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
|
||||||
|
|
||||||
|
See the Printf example for details on the setup of variables being shown
|
||||||
|
here.
|
||||||
|
|
||||||
|
Errors
|
||||||
|
|
||||||
|
Since it is possible for custom Stringer/error interfaces to panic, spew
|
||||||
|
detects them and handles them internally by printing the panic information
|
||||||
|
inline with the output. Since spew is intended to provide deep pretty printing
|
||||||
|
capabilities on structures, it intentionally does not return any errors.
|
||||||
|
*/
|
||||||
|
package spew
|
||||||
509
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
Normal file
509
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump.go
generated
vendored
Normal file
|
|
@ -0,0 +1,509 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package spew
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// uint8Type is a reflect.Type representing a uint8. It is used to
|
||||||
|
// convert cgo types to uint8 slices for hexdumping.
|
||||||
|
uint8Type = reflect.TypeOf(uint8(0))
|
||||||
|
|
||||||
|
// cCharRE is a regular expression that matches a cgo char.
|
||||||
|
// It is used to detect character arrays to hexdump them.
|
||||||
|
cCharRE = regexp.MustCompile("^.*\\._Ctype_char$")
|
||||||
|
|
||||||
|
// cUnsignedCharRE is a regular expression that matches a cgo unsigned
|
||||||
|
// char. It is used to detect unsigned character arrays to hexdump
|
||||||
|
// them.
|
||||||
|
cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$")
|
||||||
|
|
||||||
|
// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
|
||||||
|
// It is used to detect uint8_t arrays to hexdump them.
|
||||||
|
cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$")
|
||||||
|
)
|
||||||
|
|
||||||
|
// dumpState contains information about the state of a dump operation.
|
||||||
|
type dumpState struct {
|
||||||
|
w io.Writer
|
||||||
|
depth int
|
||||||
|
pointers map[uintptr]int
|
||||||
|
ignoreNextType bool
|
||||||
|
ignoreNextIndent bool
|
||||||
|
cs *ConfigState
|
||||||
|
}
|
||||||
|
|
||||||
|
// indent performs indentation according to the depth level and cs.Indent
|
||||||
|
// option.
|
||||||
|
func (d *dumpState) indent() {
|
||||||
|
if d.ignoreNextIndent {
|
||||||
|
d.ignoreNextIndent = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth))
|
||||||
|
}
|
||||||
|
|
||||||
|
// unpackValue returns values inside of non-nil interfaces when possible.
|
||||||
|
// This is useful for data types like structs, arrays, slices, and maps which
|
||||||
|
// can contain varying types packed inside an interface.
|
||||||
|
func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
|
||||||
|
if v.Kind() == reflect.Interface && !v.IsNil() {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// dumpPtr handles formatting of pointers by indirecting them as necessary.
|
||||||
|
func (d *dumpState) dumpPtr(v reflect.Value) {
|
||||||
|
// Remove pointers at or below the current depth from map used to detect
|
||||||
|
// circular refs.
|
||||||
|
for k, depth := range d.pointers {
|
||||||
|
if depth >= d.depth {
|
||||||
|
delete(d.pointers, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep list of all dereferenced pointers to show later.
|
||||||
|
pointerChain := make([]uintptr, 0)
|
||||||
|
|
||||||
|
// Figure out how many levels of indirection there are by dereferencing
|
||||||
|
// pointers and unpacking interfaces down the chain while detecting circular
|
||||||
|
// references.
|
||||||
|
nilFound := false
|
||||||
|
cycleFound := false
|
||||||
|
indirects := 0
|
||||||
|
ve := v
|
||||||
|
for ve.Kind() == reflect.Ptr {
|
||||||
|
if ve.IsNil() {
|
||||||
|
nilFound = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
indirects++
|
||||||
|
addr := ve.Pointer()
|
||||||
|
pointerChain = append(pointerChain, addr)
|
||||||
|
if pd, ok := d.pointers[addr]; ok && pd < d.depth {
|
||||||
|
cycleFound = true
|
||||||
|
indirects--
|
||||||
|
break
|
||||||
|
}
|
||||||
|
d.pointers[addr] = d.depth
|
||||||
|
|
||||||
|
ve = ve.Elem()
|
||||||
|
if ve.Kind() == reflect.Interface {
|
||||||
|
if ve.IsNil() {
|
||||||
|
nilFound = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ve = ve.Elem()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display type information.
|
||||||
|
d.w.Write(openParenBytes)
|
||||||
|
d.w.Write(bytes.Repeat(asteriskBytes, indirects))
|
||||||
|
d.w.Write([]byte(ve.Type().String()))
|
||||||
|
d.w.Write(closeParenBytes)
|
||||||
|
|
||||||
|
// Display pointer information.
|
||||||
|
if len(pointerChain) > 0 {
|
||||||
|
d.w.Write(openParenBytes)
|
||||||
|
for i, addr := range pointerChain {
|
||||||
|
if i > 0 {
|
||||||
|
d.w.Write(pointerChainBytes)
|
||||||
|
}
|
||||||
|
printHexPtr(d.w, addr)
|
||||||
|
}
|
||||||
|
d.w.Write(closeParenBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display dereferenced value.
|
||||||
|
d.w.Write(openParenBytes)
|
||||||
|
switch {
|
||||||
|
case nilFound == true:
|
||||||
|
d.w.Write(nilAngleBytes)
|
||||||
|
|
||||||
|
case cycleFound == true:
|
||||||
|
d.w.Write(circularBytes)
|
||||||
|
|
||||||
|
default:
|
||||||
|
d.ignoreNextType = true
|
||||||
|
d.dump(ve)
|
||||||
|
}
|
||||||
|
d.w.Write(closeParenBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// dumpSlice handles formatting of arrays and slices. Byte (uint8 under
|
||||||
|
// reflection) arrays and slices are dumped in hexdump -C fashion.
|
||||||
|
func (d *dumpState) dumpSlice(v reflect.Value) {
|
||||||
|
// Determine whether this type should be hex dumped or not. Also,
|
||||||
|
// for types which should be hexdumped, try to use the underlying data
|
||||||
|
// first, then fall back to trying to convert them to a uint8 slice.
|
||||||
|
var buf []uint8
|
||||||
|
doConvert := false
|
||||||
|
doHexDump := false
|
||||||
|
numEntries := v.Len()
|
||||||
|
if numEntries > 0 {
|
||||||
|
vt := v.Index(0).Type()
|
||||||
|
vts := vt.String()
|
||||||
|
switch {
|
||||||
|
// C types that need to be converted.
|
||||||
|
case cCharRE.MatchString(vts):
|
||||||
|
fallthrough
|
||||||
|
case cUnsignedCharRE.MatchString(vts):
|
||||||
|
fallthrough
|
||||||
|
case cUint8tCharRE.MatchString(vts):
|
||||||
|
doConvert = true
|
||||||
|
|
||||||
|
// Try to use existing uint8 slices and fall back to converting
|
||||||
|
// and copying if that fails.
|
||||||
|
case vt.Kind() == reflect.Uint8:
|
||||||
|
// We need an addressable interface to convert the type
|
||||||
|
// to a byte slice. However, the reflect package won't
|
||||||
|
// give us an interface on certain things like
|
||||||
|
// unexported struct fields in order to enforce
|
||||||
|
// visibility rules. We use unsafe, when available, to
|
||||||
|
// bypass these restrictions since this package does not
|
||||||
|
// mutate the values.
|
||||||
|
vs := v
|
||||||
|
if !vs.CanInterface() || !vs.CanAddr() {
|
||||||
|
vs = unsafeReflectValue(vs)
|
||||||
|
}
|
||||||
|
if !UnsafeDisabled {
|
||||||
|
vs = vs.Slice(0, numEntries)
|
||||||
|
|
||||||
|
// Use the existing uint8 slice if it can be
|
||||||
|
// type asserted.
|
||||||
|
iface := vs.Interface()
|
||||||
|
if slice, ok := iface.([]uint8); ok {
|
||||||
|
buf = slice
|
||||||
|
doHexDump = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The underlying data needs to be converted if it can't
|
||||||
|
// be type asserted to a uint8 slice.
|
||||||
|
doConvert = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy and convert the underlying type if needed.
|
||||||
|
if doConvert && vt.ConvertibleTo(uint8Type) {
|
||||||
|
// Convert and copy each element into a uint8 byte
|
||||||
|
// slice.
|
||||||
|
buf = make([]uint8, numEntries)
|
||||||
|
for i := 0; i < numEntries; i++ {
|
||||||
|
vv := v.Index(i)
|
||||||
|
buf[i] = uint8(vv.Convert(uint8Type).Uint())
|
||||||
|
}
|
||||||
|
doHexDump = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hexdump the entire slice as needed.
|
||||||
|
if doHexDump {
|
||||||
|
indent := strings.Repeat(d.cs.Indent, d.depth)
|
||||||
|
str := indent + hex.Dump(buf)
|
||||||
|
str = strings.Replace(str, "\n", "\n"+indent, -1)
|
||||||
|
str = strings.TrimRight(str, d.cs.Indent)
|
||||||
|
d.w.Write([]byte(str))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursively call dump for each item.
|
||||||
|
for i := 0; i < numEntries; i++ {
|
||||||
|
d.dump(d.unpackValue(v.Index(i)))
|
||||||
|
if i < (numEntries - 1) {
|
||||||
|
d.w.Write(commaNewlineBytes)
|
||||||
|
} else {
|
||||||
|
d.w.Write(newlineBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dump is the main workhorse for dumping a value. It uses the passed reflect
|
||||||
|
// value to figure out what kind of object we are dealing with and formats it
|
||||||
|
// appropriately. It is a recursive function, however circular data structures
|
||||||
|
// are detected and handled properly.
|
||||||
|
func (d *dumpState) dump(v reflect.Value) {
|
||||||
|
// Handle invalid reflect values immediately.
|
||||||
|
kind := v.Kind()
|
||||||
|
if kind == reflect.Invalid {
|
||||||
|
d.w.Write(invalidAngleBytes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle pointers specially.
|
||||||
|
if kind == reflect.Ptr {
|
||||||
|
d.indent()
|
||||||
|
d.dumpPtr(v)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print type information unless already handled elsewhere.
|
||||||
|
if !d.ignoreNextType {
|
||||||
|
d.indent()
|
||||||
|
d.w.Write(openParenBytes)
|
||||||
|
d.w.Write([]byte(v.Type().String()))
|
||||||
|
d.w.Write(closeParenBytes)
|
||||||
|
d.w.Write(spaceBytes)
|
||||||
|
}
|
||||||
|
d.ignoreNextType = false
|
||||||
|
|
||||||
|
// Display length and capacity if the built-in len and cap functions
|
||||||
|
// work with the value's kind and the len/cap itself is non-zero.
|
||||||
|
valueLen, valueCap := 0, 0
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Array, reflect.Slice, reflect.Chan:
|
||||||
|
valueLen, valueCap = v.Len(), v.Cap()
|
||||||
|
case reflect.Map, reflect.String:
|
||||||
|
valueLen = v.Len()
|
||||||
|
}
|
||||||
|
if valueLen != 0 || valueCap != 0 {
|
||||||
|
d.w.Write(openParenBytes)
|
||||||
|
if valueLen != 0 {
|
||||||
|
d.w.Write(lenEqualsBytes)
|
||||||
|
printInt(d.w, int64(valueLen), 10)
|
||||||
|
}
|
||||||
|
if valueCap != 0 {
|
||||||
|
if valueLen != 0 {
|
||||||
|
d.w.Write(spaceBytes)
|
||||||
|
}
|
||||||
|
d.w.Write(capEqualsBytes)
|
||||||
|
printInt(d.w, int64(valueCap), 10)
|
||||||
|
}
|
||||||
|
d.w.Write(closeParenBytes)
|
||||||
|
d.w.Write(spaceBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call Stringer/error interfaces if they exist and the handle methods flag
|
||||||
|
// is enabled
|
||||||
|
if !d.cs.DisableMethods {
|
||||||
|
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
|
||||||
|
if handled := handleMethods(d.cs, d.w, v); handled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch kind {
|
||||||
|
case reflect.Invalid:
|
||||||
|
// Do nothing. We should never get here since invalid has already
|
||||||
|
// been handled above.
|
||||||
|
|
||||||
|
case reflect.Bool:
|
||||||
|
printBool(d.w, v.Bool())
|
||||||
|
|
||||||
|
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||||
|
printInt(d.w, v.Int(), 10)
|
||||||
|
|
||||||
|
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||||
|
printUint(d.w, v.Uint(), 10)
|
||||||
|
|
||||||
|
case reflect.Float32:
|
||||||
|
printFloat(d.w, v.Float(), 32)
|
||||||
|
|
||||||
|
case reflect.Float64:
|
||||||
|
printFloat(d.w, v.Float(), 64)
|
||||||
|
|
||||||
|
case reflect.Complex64:
|
||||||
|
printComplex(d.w, v.Complex(), 32)
|
||||||
|
|
||||||
|
case reflect.Complex128:
|
||||||
|
printComplex(d.w, v.Complex(), 64)
|
||||||
|
|
||||||
|
case reflect.Slice:
|
||||||
|
if v.IsNil() {
|
||||||
|
d.w.Write(nilAngleBytes)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
|
||||||
|
case reflect.Array:
|
||||||
|
d.w.Write(openBraceNewlineBytes)
|
||||||
|
d.depth++
|
||||||
|
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
|
||||||
|
d.indent()
|
||||||
|
d.w.Write(maxNewlineBytes)
|
||||||
|
} else {
|
||||||
|
d.dumpSlice(v)
|
||||||
|
}
|
||||||
|
d.depth--
|
||||||
|
d.indent()
|
||||||
|
d.w.Write(closeBraceBytes)
|
||||||
|
|
||||||
|
case reflect.String:
|
||||||
|
d.w.Write([]byte(strconv.Quote(v.String())))
|
||||||
|
|
||||||
|
case reflect.Interface:
|
||||||
|
// The only time we should get here is for nil interfaces due to
|
||||||
|
// unpackValue calls.
|
||||||
|
if v.IsNil() {
|
||||||
|
d.w.Write(nilAngleBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Ptr:
|
||||||
|
// Do nothing. We should never get here since pointers have already
|
||||||
|
// been handled above.
|
||||||
|
|
||||||
|
case reflect.Map:
|
||||||
|
// nil maps should be indicated as different than empty maps
|
||||||
|
if v.IsNil() {
|
||||||
|
d.w.Write(nilAngleBytes)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
d.w.Write(openBraceNewlineBytes)
|
||||||
|
d.depth++
|
||||||
|
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
|
||||||
|
d.indent()
|
||||||
|
d.w.Write(maxNewlineBytes)
|
||||||
|
} else {
|
||||||
|
numEntries := v.Len()
|
||||||
|
keys := v.MapKeys()
|
||||||
|
if d.cs.SortKeys {
|
||||||
|
sortValues(keys, d.cs)
|
||||||
|
}
|
||||||
|
for i, key := range keys {
|
||||||
|
d.dump(d.unpackValue(key))
|
||||||
|
d.w.Write(colonSpaceBytes)
|
||||||
|
d.ignoreNextIndent = true
|
||||||
|
d.dump(d.unpackValue(v.MapIndex(key)))
|
||||||
|
if i < (numEntries - 1) {
|
||||||
|
d.w.Write(commaNewlineBytes)
|
||||||
|
} else {
|
||||||
|
d.w.Write(newlineBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.depth--
|
||||||
|
d.indent()
|
||||||
|
d.w.Write(closeBraceBytes)
|
||||||
|
|
||||||
|
case reflect.Struct:
|
||||||
|
d.w.Write(openBraceNewlineBytes)
|
||||||
|
d.depth++
|
||||||
|
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
|
||||||
|
d.indent()
|
||||||
|
d.w.Write(maxNewlineBytes)
|
||||||
|
} else {
|
||||||
|
vt := v.Type()
|
||||||
|
numFields := v.NumField()
|
||||||
|
for i := 0; i < numFields; i++ {
|
||||||
|
d.indent()
|
||||||
|
vtf := vt.Field(i)
|
||||||
|
d.w.Write([]byte(vtf.Name))
|
||||||
|
d.w.Write(colonSpaceBytes)
|
||||||
|
d.ignoreNextIndent = true
|
||||||
|
d.dump(d.unpackValue(v.Field(i)))
|
||||||
|
if i < (numFields - 1) {
|
||||||
|
d.w.Write(commaNewlineBytes)
|
||||||
|
} else {
|
||||||
|
d.w.Write(newlineBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.depth--
|
||||||
|
d.indent()
|
||||||
|
d.w.Write(closeBraceBytes)
|
||||||
|
|
||||||
|
case reflect.Uintptr:
|
||||||
|
printHexPtr(d.w, uintptr(v.Uint()))
|
||||||
|
|
||||||
|
case reflect.UnsafePointer, reflect.Chan, reflect.Func:
|
||||||
|
printHexPtr(d.w, v.Pointer())
|
||||||
|
|
||||||
|
// There were not any other types at the time this code was written, but
|
||||||
|
// fall back to letting the default fmt package handle it in case any new
|
||||||
|
// types are added.
|
||||||
|
default:
|
||||||
|
if v.CanInterface() {
|
||||||
|
fmt.Fprintf(d.w, "%v", v.Interface())
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(d.w, "%v", v.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fdump is a helper function to consolidate the logic from the various public
|
||||||
|
// methods which take varying writers and config states.
|
||||||
|
func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
|
||||||
|
for _, arg := range a {
|
||||||
|
if arg == nil {
|
||||||
|
w.Write(interfaceBytes)
|
||||||
|
w.Write(spaceBytes)
|
||||||
|
w.Write(nilAngleBytes)
|
||||||
|
w.Write(newlineBytes)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
d := dumpState{w: w, cs: cs}
|
||||||
|
d.pointers = make(map[uintptr]int)
|
||||||
|
d.dump(reflect.ValueOf(arg))
|
||||||
|
d.w.Write(newlineBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fdump formats and displays the passed arguments to io.Writer w. It formats
|
||||||
|
// exactly the same as Dump.
|
||||||
|
func Fdump(w io.Writer, a ...interface{}) {
|
||||||
|
fdump(&Config, w, a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sdump returns a string with the passed arguments formatted exactly the same
|
||||||
|
// as Dump.
|
||||||
|
func Sdump(a ...interface{}) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
fdump(&Config, &buf, a...)
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Dump displays the passed parameters to standard out with newlines, customizable
|
||||||
|
indentation, and additional debug information such as complete types and all
|
||||||
|
pointer addresses used to indirect to the final value. It provides the
|
||||||
|
following features over the built-in printing facilities provided by the fmt
|
||||||
|
package:
|
||||||
|
|
||||||
|
* Pointers are dereferenced and followed
|
||||||
|
* Circular data structures are detected and handled properly
|
||||||
|
* Custom Stringer/error interfaces are optionally invoked, including
|
||||||
|
on unexported types
|
||||||
|
* Custom types which only implement the Stringer/error interfaces via
|
||||||
|
a pointer receiver are optionally invoked when passing non-pointer
|
||||||
|
variables
|
||||||
|
* Byte arrays and slices are dumped like the hexdump -C command which
|
||||||
|
includes offsets, byte values in hex, and ASCII output
|
||||||
|
|
||||||
|
The configuration options are controlled by an exported package global,
|
||||||
|
spew.Config. See ConfigState for options documentation.
|
||||||
|
|
||||||
|
See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
|
||||||
|
get the formatted result as a string.
|
||||||
|
*/
|
||||||
|
func Dump(a ...interface{}) {
|
||||||
|
fdump(&Config, os.Stdout, a...)
|
||||||
|
}
|
||||||
1042
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump_test.go
generated
vendored
Normal file
1042
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
98
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go
generated
vendored
Normal file
98
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
// Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||||
|
// when both cgo is supported and "-tags testcgo" is added to the go test
|
||||||
|
// command line. This means the cgo tests are only added (and hence run) when
|
||||||
|
// specifially requested. This configuration is used because spew itself
|
||||||
|
// does not require cgo to run even though it does handle certain cgo types
|
||||||
|
// specially. Rather than forcing all clients to require cgo and an external
|
||||||
|
// C compiler just to run the tests, this scheme makes them optional.
|
||||||
|
// +build cgo,testcgo
|
||||||
|
|
||||||
|
package spew_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew/testdata"
|
||||||
|
)
|
||||||
|
|
||||||
|
func addCgoDumpTests() {
|
||||||
|
// C char pointer.
|
||||||
|
v := testdata.GetCgoCharPointer()
|
||||||
|
nv := testdata.GetCgoNullCharPointer()
|
||||||
|
pv := &v
|
||||||
|
vcAddr := fmt.Sprintf("%p", v)
|
||||||
|
vAddr := fmt.Sprintf("%p", pv)
|
||||||
|
pvAddr := fmt.Sprintf("%p", &pv)
|
||||||
|
vt := "*testdata._Ctype_char"
|
||||||
|
vs := "116"
|
||||||
|
addDumpTest(v, "("+vt+")("+vcAddr+")("+vs+")\n")
|
||||||
|
addDumpTest(pv, "(*"+vt+")("+vAddr+"->"+vcAddr+")("+vs+")\n")
|
||||||
|
addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+"->"+vcAddr+")("+vs+")\n")
|
||||||
|
addDumpTest(nv, "("+vt+")(<nil>)\n")
|
||||||
|
|
||||||
|
// C char array.
|
||||||
|
v2, v2l, v2c := testdata.GetCgoCharArray()
|
||||||
|
v2Len := fmt.Sprintf("%d", v2l)
|
||||||
|
v2Cap := fmt.Sprintf("%d", v2c)
|
||||||
|
v2t := "[6]testdata._Ctype_char"
|
||||||
|
v2s := "(len=" + v2Len + " cap=" + v2Cap + ") " +
|
||||||
|
"{\n 00000000 74 65 73 74 32 00 " +
|
||||||
|
" |test2.|\n}"
|
||||||
|
addDumpTest(v2, "("+v2t+") "+v2s+"\n")
|
||||||
|
|
||||||
|
// C unsigned char array.
|
||||||
|
v3, v3l, v3c := testdata.GetCgoUnsignedCharArray()
|
||||||
|
v3Len := fmt.Sprintf("%d", v3l)
|
||||||
|
v3Cap := fmt.Sprintf("%d", v3c)
|
||||||
|
v3t := "[6]testdata._Ctype_unsignedchar"
|
||||||
|
v3s := "(len=" + v3Len + " cap=" + v3Cap + ") " +
|
||||||
|
"{\n 00000000 74 65 73 74 33 00 " +
|
||||||
|
" |test3.|\n}"
|
||||||
|
addDumpTest(v3, "("+v3t+") "+v3s+"\n")
|
||||||
|
|
||||||
|
// C signed char array.
|
||||||
|
v4, v4l, v4c := testdata.GetCgoSignedCharArray()
|
||||||
|
v4Len := fmt.Sprintf("%d", v4l)
|
||||||
|
v4Cap := fmt.Sprintf("%d", v4c)
|
||||||
|
v4t := "[6]testdata._Ctype_schar"
|
||||||
|
v4t2 := "testdata._Ctype_schar"
|
||||||
|
v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " +
|
||||||
|
"{\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 101,\n (" + v4t2 +
|
||||||
|
") 115,\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 52,\n (" + v4t2 +
|
||||||
|
") 0\n}"
|
||||||
|
addDumpTest(v4, "("+v4t+") "+v4s+"\n")
|
||||||
|
|
||||||
|
// C uint8_t array.
|
||||||
|
v5, v5l, v5c := testdata.GetCgoUint8tArray()
|
||||||
|
v5Len := fmt.Sprintf("%d", v5l)
|
||||||
|
v5Cap := fmt.Sprintf("%d", v5c)
|
||||||
|
v5t := "[6]testdata._Ctype_uint8_t"
|
||||||
|
v5s := "(len=" + v5Len + " cap=" + v5Cap + ") " +
|
||||||
|
"{\n 00000000 74 65 73 74 35 00 " +
|
||||||
|
" |test5.|\n}"
|
||||||
|
addDumpTest(v5, "("+v5t+") "+v5s+"\n")
|
||||||
|
|
||||||
|
// C typedefed unsigned char array.
|
||||||
|
v6, v6l, v6c := testdata.GetCgoTypdefedUnsignedCharArray()
|
||||||
|
v6Len := fmt.Sprintf("%d", v6l)
|
||||||
|
v6Cap := fmt.Sprintf("%d", v6c)
|
||||||
|
v6t := "[6]testdata._Ctype_custom_uchar_t"
|
||||||
|
v6s := "(len=" + v6Len + " cap=" + v6Cap + ") " +
|
||||||
|
"{\n 00000000 74 65 73 74 36 00 " +
|
||||||
|
" |test6.|\n}"
|
||||||
|
addDumpTest(v6, "("+v6t+") "+v6s+"\n")
|
||||||
|
}
|
||||||
26
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go
generated
vendored
Normal file
26
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||||
|
//
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||||
|
// when either cgo is not supported or "-tags testcgo" is not added to the go
|
||||||
|
// test command line. This file intentionally does not setup any cgo tests in
|
||||||
|
// this scenario.
|
||||||
|
// +build !cgo !testcgo
|
||||||
|
|
||||||
|
package spew_test
|
||||||
|
|
||||||
|
func addCgoDumpTests() {
|
||||||
|
// Don't add any tests for cgo since this file is only compiled when
|
||||||
|
// there should not be any cgo tests.
|
||||||
|
}
|
||||||
226
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/example_test.go
generated
vendored
Normal file
226
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/example_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,226 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package spew_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Flag int
|
||||||
|
|
||||||
|
const (
|
||||||
|
flagOne Flag = iota
|
||||||
|
flagTwo
|
||||||
|
)
|
||||||
|
|
||||||
|
var flagStrings = map[Flag]string{
|
||||||
|
flagOne: "flagOne",
|
||||||
|
flagTwo: "flagTwo",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f Flag) String() string {
|
||||||
|
if s, ok := flagStrings[f]; ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Unknown flag (%d)", int(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bar struct {
|
||||||
|
data uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type Foo struct {
|
||||||
|
unexportedField Bar
|
||||||
|
ExportedField map[interface{}]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This example demonstrates how to use Dump to dump variables to stdout.
|
||||||
|
func ExampleDump() {
|
||||||
|
// The following package level declarations are assumed for this example:
|
||||||
|
/*
|
||||||
|
type Flag int
|
||||||
|
|
||||||
|
const (
|
||||||
|
flagOne Flag = iota
|
||||||
|
flagTwo
|
||||||
|
)
|
||||||
|
|
||||||
|
var flagStrings = map[Flag]string{
|
||||||
|
flagOne: "flagOne",
|
||||||
|
flagTwo: "flagTwo",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f Flag) String() string {
|
||||||
|
if s, ok := flagStrings[f]; ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Unknown flag (%d)", int(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bar struct {
|
||||||
|
data uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type Foo struct {
|
||||||
|
unexportedField Bar
|
||||||
|
ExportedField map[interface{}]interface{}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Setup some sample data structures for the example.
|
||||||
|
bar := Bar{uintptr(0)}
|
||||||
|
s1 := Foo{bar, map[interface{}]interface{}{"one": true}}
|
||||||
|
f := Flag(5)
|
||||||
|
b := []byte{
|
||||||
|
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
|
||||||
|
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
||||||
|
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||||
|
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
|
||||||
|
0x31, 0x32,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump!
|
||||||
|
spew.Dump(s1, f, b)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// (spew_test.Foo) {
|
||||||
|
// unexportedField: (spew_test.Bar) {
|
||||||
|
// data: (uintptr) <nil>
|
||||||
|
// },
|
||||||
|
// ExportedField: (map[interface {}]interface {}) (len=1) {
|
||||||
|
// (string) (len=3) "one": (bool) true
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// (spew_test.Flag) Unknown flag (5)
|
||||||
|
// ([]uint8) (len=34 cap=34) {
|
||||||
|
// 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
|
||||||
|
// 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
|
||||||
|
// 00000020 31 32 |12|
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
// This example demonstrates how to use Printf to display a variable with a
|
||||||
|
// format string and inline formatting.
|
||||||
|
func ExamplePrintf() {
|
||||||
|
// Create a double pointer to a uint 8.
|
||||||
|
ui8 := uint8(5)
|
||||||
|
pui8 := &ui8
|
||||||
|
ppui8 := &pui8
|
||||||
|
|
||||||
|
// Create a circular data type.
|
||||||
|
type circular struct {
|
||||||
|
ui8 uint8
|
||||||
|
c *circular
|
||||||
|
}
|
||||||
|
c := circular{ui8: 1}
|
||||||
|
c.c = &c
|
||||||
|
|
||||||
|
// Print!
|
||||||
|
spew.Printf("ppui8: %v\n", ppui8)
|
||||||
|
spew.Printf("circular: %v\n", c)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// ppui8: <**>5
|
||||||
|
// circular: {1 <*>{1 <*><shown>}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This example demonstrates how to use a ConfigState.
|
||||||
|
func ExampleConfigState() {
|
||||||
|
// Modify the indent level of the ConfigState only. The global
|
||||||
|
// configuration is not modified.
|
||||||
|
scs := spew.ConfigState{Indent: "\t"}
|
||||||
|
|
||||||
|
// Output using the ConfigState instance.
|
||||||
|
v := map[string]int{"one": 1}
|
||||||
|
scs.Printf("v: %v\n", v)
|
||||||
|
scs.Dump(v)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// v: map[one:1]
|
||||||
|
// (map[string]int) (len=1) {
|
||||||
|
// (string) (len=3) "one": (int) 1
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// This example demonstrates how to use ConfigState.Dump to dump variables to
|
||||||
|
// stdout
|
||||||
|
func ExampleConfigState_Dump() {
|
||||||
|
// See the top-level Dump example for details on the types used in this
|
||||||
|
// example.
|
||||||
|
|
||||||
|
// Create two ConfigState instances with different indentation.
|
||||||
|
scs := spew.ConfigState{Indent: "\t"}
|
||||||
|
scs2 := spew.ConfigState{Indent: " "}
|
||||||
|
|
||||||
|
// Setup some sample data structures for the example.
|
||||||
|
bar := Bar{uintptr(0)}
|
||||||
|
s1 := Foo{bar, map[interface{}]interface{}{"one": true}}
|
||||||
|
|
||||||
|
// Dump using the ConfigState instances.
|
||||||
|
scs.Dump(s1)
|
||||||
|
scs2.Dump(s1)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// (spew_test.Foo) {
|
||||||
|
// unexportedField: (spew_test.Bar) {
|
||||||
|
// data: (uintptr) <nil>
|
||||||
|
// },
|
||||||
|
// ExportedField: (map[interface {}]interface {}) (len=1) {
|
||||||
|
// (string) (len=3) "one": (bool) true
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// (spew_test.Foo) {
|
||||||
|
// unexportedField: (spew_test.Bar) {
|
||||||
|
// data: (uintptr) <nil>
|
||||||
|
// },
|
||||||
|
// ExportedField: (map[interface {}]interface {}) (len=1) {
|
||||||
|
// (string) (len=3) "one": (bool) true
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
// This example demonstrates how to use ConfigState.Printf to display a variable
|
||||||
|
// with a format string and inline formatting.
|
||||||
|
func ExampleConfigState_Printf() {
|
||||||
|
// See the top-level Dump example for details on the types used in this
|
||||||
|
// example.
|
||||||
|
|
||||||
|
// Create two ConfigState instances and modify the method handling of the
|
||||||
|
// first ConfigState only.
|
||||||
|
scs := spew.NewDefaultConfig()
|
||||||
|
scs2 := spew.NewDefaultConfig()
|
||||||
|
scs.DisableMethods = true
|
||||||
|
|
||||||
|
// Alternatively
|
||||||
|
// scs := spew.ConfigState{Indent: " ", DisableMethods: true}
|
||||||
|
// scs2 := spew.ConfigState{Indent: " "}
|
||||||
|
|
||||||
|
// This is of type Flag which implements a Stringer and has raw value 1.
|
||||||
|
f := flagTwo
|
||||||
|
|
||||||
|
// Dump using the ConfigState instances.
|
||||||
|
scs.Printf("f: %v\n", f)
|
||||||
|
scs2.Printf("f: %v\n", f)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// f: 1
|
||||||
|
// f: flagTwo
|
||||||
|
}
|
||||||
419
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format.go
generated
vendored
Normal file
419
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format.go
generated
vendored
Normal file
|
|
@ -0,0 +1,419 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package spew
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// supportedFlags is a list of all the character flags supported by fmt package.
|
||||||
|
const supportedFlags = "0-+# "
|
||||||
|
|
||||||
|
// formatState implements the fmt.Formatter interface and contains information
|
||||||
|
// about the state of a formatting operation. The NewFormatter function can
|
||||||
|
// be used to get a new Formatter which can be used directly as arguments
|
||||||
|
// in standard fmt package printing calls.
|
||||||
|
type formatState struct {
|
||||||
|
value interface{}
|
||||||
|
fs fmt.State
|
||||||
|
depth int
|
||||||
|
pointers map[uintptr]int
|
||||||
|
ignoreNextType bool
|
||||||
|
cs *ConfigState
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildDefaultFormat recreates the original format string without precision
|
||||||
|
// and width information to pass in to fmt.Sprintf in the case of an
|
||||||
|
// unrecognized type. Unless new types are added to the language, this
|
||||||
|
// function won't ever be called.
|
||||||
|
func (f *formatState) buildDefaultFormat() (format string) {
|
||||||
|
buf := bytes.NewBuffer(percentBytes)
|
||||||
|
|
||||||
|
for _, flag := range supportedFlags {
|
||||||
|
if f.fs.Flag(int(flag)) {
|
||||||
|
buf.WriteRune(flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteRune('v')
|
||||||
|
|
||||||
|
format = buf.String()
|
||||||
|
return format
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructOrigFormat recreates the original format string including precision
|
||||||
|
// and width information to pass along to the standard fmt package. This allows
|
||||||
|
// automatic deferral of all format strings this package doesn't support.
|
||||||
|
func (f *formatState) constructOrigFormat(verb rune) (format string) {
|
||||||
|
buf := bytes.NewBuffer(percentBytes)
|
||||||
|
|
||||||
|
for _, flag := range supportedFlags {
|
||||||
|
if f.fs.Flag(int(flag)) {
|
||||||
|
buf.WriteRune(flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if width, ok := f.fs.Width(); ok {
|
||||||
|
buf.WriteString(strconv.Itoa(width))
|
||||||
|
}
|
||||||
|
|
||||||
|
if precision, ok := f.fs.Precision(); ok {
|
||||||
|
buf.Write(precisionBytes)
|
||||||
|
buf.WriteString(strconv.Itoa(precision))
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteRune(verb)
|
||||||
|
|
||||||
|
format = buf.String()
|
||||||
|
return format
|
||||||
|
}
|
||||||
|
|
||||||
|
// unpackValue returns values inside of non-nil interfaces when possible and
|
||||||
|
// ensures that types for values which have been unpacked from an interface
|
||||||
|
// are displayed when the show types flag is also set.
|
||||||
|
// This is useful for data types like structs, arrays, slices, and maps which
|
||||||
|
// can contain varying types packed inside an interface.
|
||||||
|
func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
|
||||||
|
if v.Kind() == reflect.Interface {
|
||||||
|
f.ignoreNextType = false
|
||||||
|
if !v.IsNil() {
|
||||||
|
v = v.Elem()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatPtr handles formatting of pointers by indirecting them as necessary.
|
||||||
|
func (f *formatState) formatPtr(v reflect.Value) {
|
||||||
|
// Display nil if top level pointer is nil.
|
||||||
|
showTypes := f.fs.Flag('#')
|
||||||
|
if v.IsNil() && (!showTypes || f.ignoreNextType) {
|
||||||
|
f.fs.Write(nilAngleBytes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove pointers at or below the current depth from map used to detect
|
||||||
|
// circular refs.
|
||||||
|
for k, depth := range f.pointers {
|
||||||
|
if depth >= f.depth {
|
||||||
|
delete(f.pointers, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep list of all dereferenced pointers to possibly show later.
|
||||||
|
pointerChain := make([]uintptr, 0)
|
||||||
|
|
||||||
|
// Figure out how many levels of indirection there are by derferencing
|
||||||
|
// pointers and unpacking interfaces down the chain while detecting circular
|
||||||
|
// references.
|
||||||
|
nilFound := false
|
||||||
|
cycleFound := false
|
||||||
|
indirects := 0
|
||||||
|
ve := v
|
||||||
|
for ve.Kind() == reflect.Ptr {
|
||||||
|
if ve.IsNil() {
|
||||||
|
nilFound = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
indirects++
|
||||||
|
addr := ve.Pointer()
|
||||||
|
pointerChain = append(pointerChain, addr)
|
||||||
|
if pd, ok := f.pointers[addr]; ok && pd < f.depth {
|
||||||
|
cycleFound = true
|
||||||
|
indirects--
|
||||||
|
break
|
||||||
|
}
|
||||||
|
f.pointers[addr] = f.depth
|
||||||
|
|
||||||
|
ve = ve.Elem()
|
||||||
|
if ve.Kind() == reflect.Interface {
|
||||||
|
if ve.IsNil() {
|
||||||
|
nilFound = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
ve = ve.Elem()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display type or indirection level depending on flags.
|
||||||
|
if showTypes && !f.ignoreNextType {
|
||||||
|
f.fs.Write(openParenBytes)
|
||||||
|
f.fs.Write(bytes.Repeat(asteriskBytes, indirects))
|
||||||
|
f.fs.Write([]byte(ve.Type().String()))
|
||||||
|
f.fs.Write(closeParenBytes)
|
||||||
|
} else {
|
||||||
|
if nilFound || cycleFound {
|
||||||
|
indirects += strings.Count(ve.Type().String(), "*")
|
||||||
|
}
|
||||||
|
f.fs.Write(openAngleBytes)
|
||||||
|
f.fs.Write([]byte(strings.Repeat("*", indirects)))
|
||||||
|
f.fs.Write(closeAngleBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display pointer information depending on flags.
|
||||||
|
if f.fs.Flag('+') && (len(pointerChain) > 0) {
|
||||||
|
f.fs.Write(openParenBytes)
|
||||||
|
for i, addr := range pointerChain {
|
||||||
|
if i > 0 {
|
||||||
|
f.fs.Write(pointerChainBytes)
|
||||||
|
}
|
||||||
|
printHexPtr(f.fs, addr)
|
||||||
|
}
|
||||||
|
f.fs.Write(closeParenBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display dereferenced value.
|
||||||
|
switch {
|
||||||
|
case nilFound == true:
|
||||||
|
f.fs.Write(nilAngleBytes)
|
||||||
|
|
||||||
|
case cycleFound == true:
|
||||||
|
f.fs.Write(circularShortBytes)
|
||||||
|
|
||||||
|
default:
|
||||||
|
f.ignoreNextType = true
|
||||||
|
f.format(ve)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// format is the main workhorse for providing the Formatter interface. It
|
||||||
|
// uses the passed reflect value to figure out what kind of object we are
|
||||||
|
// dealing with and formats it appropriately. It is a recursive function,
|
||||||
|
// however circular data structures are detected and handled properly.
|
||||||
|
func (f *formatState) format(v reflect.Value) {
|
||||||
|
// Handle invalid reflect values immediately.
|
||||||
|
kind := v.Kind()
|
||||||
|
if kind == reflect.Invalid {
|
||||||
|
f.fs.Write(invalidAngleBytes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle pointers specially.
|
||||||
|
if kind == reflect.Ptr {
|
||||||
|
f.formatPtr(v)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print type information unless already handled elsewhere.
|
||||||
|
if !f.ignoreNextType && f.fs.Flag('#') {
|
||||||
|
f.fs.Write(openParenBytes)
|
||||||
|
f.fs.Write([]byte(v.Type().String()))
|
||||||
|
f.fs.Write(closeParenBytes)
|
||||||
|
}
|
||||||
|
f.ignoreNextType = false
|
||||||
|
|
||||||
|
// Call Stringer/error interfaces if they exist and the handle methods
|
||||||
|
// flag is enabled.
|
||||||
|
if !f.cs.DisableMethods {
|
||||||
|
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
|
||||||
|
if handled := handleMethods(f.cs, f.fs, v); handled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch kind {
|
||||||
|
case reflect.Invalid:
|
||||||
|
// Do nothing. We should never get here since invalid has already
|
||||||
|
// been handled above.
|
||||||
|
|
||||||
|
case reflect.Bool:
|
||||||
|
printBool(f.fs, v.Bool())
|
||||||
|
|
||||||
|
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
|
||||||
|
printInt(f.fs, v.Int(), 10)
|
||||||
|
|
||||||
|
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
|
||||||
|
printUint(f.fs, v.Uint(), 10)
|
||||||
|
|
||||||
|
case reflect.Float32:
|
||||||
|
printFloat(f.fs, v.Float(), 32)
|
||||||
|
|
||||||
|
case reflect.Float64:
|
||||||
|
printFloat(f.fs, v.Float(), 64)
|
||||||
|
|
||||||
|
case reflect.Complex64:
|
||||||
|
printComplex(f.fs, v.Complex(), 32)
|
||||||
|
|
||||||
|
case reflect.Complex128:
|
||||||
|
printComplex(f.fs, v.Complex(), 64)
|
||||||
|
|
||||||
|
case reflect.Slice:
|
||||||
|
if v.IsNil() {
|
||||||
|
f.fs.Write(nilAngleBytes)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
|
||||||
|
case reflect.Array:
|
||||||
|
f.fs.Write(openBracketBytes)
|
||||||
|
f.depth++
|
||||||
|
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
|
||||||
|
f.fs.Write(maxShortBytes)
|
||||||
|
} else {
|
||||||
|
numEntries := v.Len()
|
||||||
|
for i := 0; i < numEntries; i++ {
|
||||||
|
if i > 0 {
|
||||||
|
f.fs.Write(spaceBytes)
|
||||||
|
}
|
||||||
|
f.ignoreNextType = true
|
||||||
|
f.format(f.unpackValue(v.Index(i)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.depth--
|
||||||
|
f.fs.Write(closeBracketBytes)
|
||||||
|
|
||||||
|
case reflect.String:
|
||||||
|
f.fs.Write([]byte(v.String()))
|
||||||
|
|
||||||
|
case reflect.Interface:
|
||||||
|
// The only time we should get here is for nil interfaces due to
|
||||||
|
// unpackValue calls.
|
||||||
|
if v.IsNil() {
|
||||||
|
f.fs.Write(nilAngleBytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
case reflect.Ptr:
|
||||||
|
// Do nothing. We should never get here since pointers have already
|
||||||
|
// been handled above.
|
||||||
|
|
||||||
|
case reflect.Map:
|
||||||
|
// nil maps should be indicated as different than empty maps
|
||||||
|
if v.IsNil() {
|
||||||
|
f.fs.Write(nilAngleBytes)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
f.fs.Write(openMapBytes)
|
||||||
|
f.depth++
|
||||||
|
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
|
||||||
|
f.fs.Write(maxShortBytes)
|
||||||
|
} else {
|
||||||
|
keys := v.MapKeys()
|
||||||
|
if f.cs.SortKeys {
|
||||||
|
sortValues(keys, f.cs)
|
||||||
|
}
|
||||||
|
for i, key := range keys {
|
||||||
|
if i > 0 {
|
||||||
|
f.fs.Write(spaceBytes)
|
||||||
|
}
|
||||||
|
f.ignoreNextType = true
|
||||||
|
f.format(f.unpackValue(key))
|
||||||
|
f.fs.Write(colonBytes)
|
||||||
|
f.ignoreNextType = true
|
||||||
|
f.format(f.unpackValue(v.MapIndex(key)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.depth--
|
||||||
|
f.fs.Write(closeMapBytes)
|
||||||
|
|
||||||
|
case reflect.Struct:
|
||||||
|
numFields := v.NumField()
|
||||||
|
f.fs.Write(openBraceBytes)
|
||||||
|
f.depth++
|
||||||
|
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
|
||||||
|
f.fs.Write(maxShortBytes)
|
||||||
|
} else {
|
||||||
|
vt := v.Type()
|
||||||
|
for i := 0; i < numFields; i++ {
|
||||||
|
if i > 0 {
|
||||||
|
f.fs.Write(spaceBytes)
|
||||||
|
}
|
||||||
|
vtf := vt.Field(i)
|
||||||
|
if f.fs.Flag('+') || f.fs.Flag('#') {
|
||||||
|
f.fs.Write([]byte(vtf.Name))
|
||||||
|
f.fs.Write(colonBytes)
|
||||||
|
}
|
||||||
|
f.format(f.unpackValue(v.Field(i)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.depth--
|
||||||
|
f.fs.Write(closeBraceBytes)
|
||||||
|
|
||||||
|
case reflect.Uintptr:
|
||||||
|
printHexPtr(f.fs, uintptr(v.Uint()))
|
||||||
|
|
||||||
|
case reflect.UnsafePointer, reflect.Chan, reflect.Func:
|
||||||
|
printHexPtr(f.fs, v.Pointer())
|
||||||
|
|
||||||
|
// There were not any other types at the time this code was written, but
|
||||||
|
// fall back to letting the default fmt package handle it if any get added.
|
||||||
|
default:
|
||||||
|
format := f.buildDefaultFormat()
|
||||||
|
if v.CanInterface() {
|
||||||
|
fmt.Fprintf(f.fs, format, v.Interface())
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(f.fs, format, v.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format satisfies the fmt.Formatter interface. See NewFormatter for usage
|
||||||
|
// details.
|
||||||
|
func (f *formatState) Format(fs fmt.State, verb rune) {
|
||||||
|
f.fs = fs
|
||||||
|
|
||||||
|
// Use standard formatting for verbs that are not v.
|
||||||
|
if verb != 'v' {
|
||||||
|
format := f.constructOrigFormat(verb)
|
||||||
|
fmt.Fprintf(fs, format, f.value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.value == nil {
|
||||||
|
if fs.Flag('#') {
|
||||||
|
fs.Write(interfaceBytes)
|
||||||
|
}
|
||||||
|
fs.Write(nilAngleBytes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
f.format(reflect.ValueOf(f.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
// newFormatter is a helper function to consolidate the logic from the various
|
||||||
|
// public methods which take varying config states.
|
||||||
|
func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
|
||||||
|
fs := &formatState{value: v, cs: cs}
|
||||||
|
fs.pointers = make(map[uintptr]int)
|
||||||
|
return fs
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
NewFormatter returns a custom formatter that satisfies the fmt.Formatter
|
||||||
|
interface. As a result, it integrates cleanly with standard fmt package
|
||||||
|
printing functions. The formatter is useful for inline printing of smaller data
|
||||||
|
types similar to the standard %v format specifier.
|
||||||
|
|
||||||
|
The custom formatter only responds to the %v (most compact), %+v (adds pointer
|
||||||
|
addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
|
||||||
|
combinations. Any other verbs such as %x and %q will be sent to the the
|
||||||
|
standard fmt package for formatting. In addition, the custom formatter ignores
|
||||||
|
the width and precision arguments (however they will still work on the format
|
||||||
|
specifiers not handled by the custom formatter).
|
||||||
|
|
||||||
|
Typically this function shouldn't be called directly. It is much easier to make
|
||||||
|
use of the custom formatter by calling one of the convenience functions such as
|
||||||
|
Printf, Println, or Fprintf.
|
||||||
|
*/
|
||||||
|
func NewFormatter(v interface{}) fmt.Formatter {
|
||||||
|
return newFormatter(&Config, v)
|
||||||
|
}
|
||||||
1558
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format_test.go
generated
vendored
Normal file
1558
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
87
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internal_test.go
generated
vendored
Normal file
87
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internal_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
This test file is part of the spew package rather than than the spew_test
|
||||||
|
package because it needs access to internals to properly test certain cases
|
||||||
|
which are not possible via the public interface since they should never happen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package spew
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// dummyFmtState implements a fake fmt.State to use for testing invalid
|
||||||
|
// reflect.Value handling. This is necessary because the fmt package catches
|
||||||
|
// invalid values before invoking the formatter on them.
|
||||||
|
type dummyFmtState struct {
|
||||||
|
bytes.Buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dfs *dummyFmtState) Flag(f int) bool {
|
||||||
|
if f == int('+') {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dfs *dummyFmtState) Precision() (int, bool) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (dfs *dummyFmtState) Width() (int, bool) {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestInvalidReflectValue ensures the dump and formatter code handles an
|
||||||
|
// invalid reflect value properly. This needs access to internal state since it
|
||||||
|
// should never happen in real code and therefore can't be tested via the public
|
||||||
|
// API.
|
||||||
|
func TestInvalidReflectValue(t *testing.T) {
|
||||||
|
i := 1
|
||||||
|
|
||||||
|
// Dump invalid reflect value.
|
||||||
|
v := new(reflect.Value)
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
d := dumpState{w: buf, cs: &Config}
|
||||||
|
d.dump(*v)
|
||||||
|
s := buf.String()
|
||||||
|
want := "<invalid>"
|
||||||
|
if s != want {
|
||||||
|
t.Errorf("InvalidReflectValue #%d\n got: %s want: %s", i, s, want)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
|
||||||
|
// Formatter invalid reflect value.
|
||||||
|
buf2 := new(dummyFmtState)
|
||||||
|
f := formatState{value: *v, cs: &Config, fs: buf2}
|
||||||
|
f.format(*v)
|
||||||
|
s = buf2.String()
|
||||||
|
want = "<invalid>"
|
||||||
|
if s != want {
|
||||||
|
t.Errorf("InvalidReflectValue #%d got: %s want: %s", i, s, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SortValues makes the internal sortValues function available to the test
|
||||||
|
// package.
|
||||||
|
func SortValues(values []reflect.Value, cs *ConfigState) {
|
||||||
|
sortValues(values, cs)
|
||||||
|
}
|
||||||
101
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go
generated
vendored
Normal file
101
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internalunsafe_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
// Copyright (c) 2013-2015 Dave Collins <dave@davec.name>
|
||||||
|
|
||||||
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
|
// NOTE: Due to the following build constraints, this file will only be compiled
|
||||||
|
// when the code is not running on Google App Engine and "-tags disableunsafe"
|
||||||
|
// is not added to the go build command line.
|
||||||
|
// +build !appengine,!disableunsafe
|
||||||
|
|
||||||
|
/*
|
||||||
|
This test file is part of the spew package rather than than the spew_test
|
||||||
|
package because it needs access to internals to properly test certain cases
|
||||||
|
which are not possible via the public interface since they should never happen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package spew
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
// changeKind uses unsafe to intentionally change the kind of a reflect.Value to
|
||||||
|
// the maximum kind value which does not exist. This is needed to test the
|
||||||
|
// fallback code which punts to the standard fmt library for new types that
|
||||||
|
// might get added to the language.
|
||||||
|
func changeKind(v *reflect.Value, readOnly bool) {
|
||||||
|
rvf := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + offsetFlag))
|
||||||
|
*rvf = *rvf | ((1<<flagKindWidth - 1) << flagKindShift)
|
||||||
|
if readOnly {
|
||||||
|
*rvf |= flagRO
|
||||||
|
} else {
|
||||||
|
*rvf &= ^uintptr(flagRO)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestAddedReflectValue tests functionaly of the dump and formatter code which
|
||||||
|
// falls back to the standard fmt library for new types that might get added to
|
||||||
|
// the language.
|
||||||
|
func TestAddedReflectValue(t *testing.T) {
|
||||||
|
i := 1
|
||||||
|
|
||||||
|
// Dump using a reflect.Value that is exported.
|
||||||
|
v := reflect.ValueOf(int8(5))
|
||||||
|
changeKind(&v, false)
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
d := dumpState{w: buf, cs: &Config}
|
||||||
|
d.dump(v)
|
||||||
|
s := buf.String()
|
||||||
|
want := "(int8) 5"
|
||||||
|
if s != want {
|
||||||
|
t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
|
||||||
|
// Dump using a reflect.Value that is not exported.
|
||||||
|
changeKind(&v, true)
|
||||||
|
buf.Reset()
|
||||||
|
d.dump(v)
|
||||||
|
s = buf.String()
|
||||||
|
want = "(int8) <int8 Value>"
|
||||||
|
if s != want {
|
||||||
|
t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
|
||||||
|
// Formatter using a reflect.Value that is exported.
|
||||||
|
changeKind(&v, false)
|
||||||
|
buf2 := new(dummyFmtState)
|
||||||
|
f := formatState{value: v, cs: &Config, fs: buf2}
|
||||||
|
f.format(v)
|
||||||
|
s = buf2.String()
|
||||||
|
want = "5"
|
||||||
|
if s != want {
|
||||||
|
t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
|
||||||
|
// Formatter using a reflect.Value that is not exported.
|
||||||
|
changeKind(&v, true)
|
||||||
|
buf2.Reset()
|
||||||
|
f = formatState{value: v, cs: &Config, fs: buf2}
|
||||||
|
f.format(v)
|
||||||
|
s = buf2.String()
|
||||||
|
want = "<int8 Value>"
|
||||||
|
if s != want {
|
||||||
|
t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
148
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew.go
generated
vendored
Normal file
148
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew.go
generated
vendored
Normal file
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package spew
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
|
||||||
|
// passed with a default Formatter interface returned by NewFormatter. It
|
||||||
|
// returns the formatted string as a value that satisfies error. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||||
|
func Errorf(format string, a ...interface{}) (err error) {
|
||||||
|
return fmt.Errorf(format, convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
|
||||||
|
// passed with a default Formatter interface returned by NewFormatter. It
|
||||||
|
// returns the number of bytes written and any write error encountered. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||||
|
func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
|
||||||
|
return fmt.Fprint(w, convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
|
||||||
|
// passed with a default Formatter interface returned by NewFormatter. It
|
||||||
|
// returns the number of bytes written and any write error encountered. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||||
|
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
|
||||||
|
return fmt.Fprintf(w, format, convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
|
||||||
|
// passed with a default Formatter interface returned by NewFormatter. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||||
|
func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
|
||||||
|
return fmt.Fprintln(w, convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print is a wrapper for fmt.Print that treats each argument as if it were
|
||||||
|
// passed with a default Formatter interface returned by NewFormatter. It
|
||||||
|
// returns the number of bytes written and any write error encountered. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b))
|
||||||
|
func Print(a ...interface{}) (n int, err error) {
|
||||||
|
return fmt.Print(convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printf is a wrapper for fmt.Printf that treats each argument as if it were
|
||||||
|
// passed with a default Formatter interface returned by NewFormatter. It
|
||||||
|
// returns the number of bytes written and any write error encountered. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||||
|
func Printf(format string, a ...interface{}) (n int, err error) {
|
||||||
|
return fmt.Printf(format, convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Println is a wrapper for fmt.Println that treats each argument as if it were
|
||||||
|
// passed with a default Formatter interface returned by NewFormatter. It
|
||||||
|
// returns the number of bytes written and any write error encountered. See
|
||||||
|
// NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b))
|
||||||
|
func Println(a ...interface{}) (n int, err error) {
|
||||||
|
return fmt.Println(convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
|
||||||
|
// passed with a default Formatter interface returned by NewFormatter. It
|
||||||
|
// returns the resulting string. See NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b))
|
||||||
|
func Sprint(a ...interface{}) string {
|
||||||
|
return fmt.Sprint(convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
|
||||||
|
// passed with a default Formatter interface returned by NewFormatter. It
|
||||||
|
// returns the resulting string. See NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b))
|
||||||
|
func Sprintf(format string, a ...interface{}) string {
|
||||||
|
return fmt.Sprintf(format, convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
|
||||||
|
// were passed with a default Formatter interface returned by NewFormatter. It
|
||||||
|
// returns the resulting string. See NewFormatter for formatting details.
|
||||||
|
//
|
||||||
|
// This function is shorthand for the following syntax:
|
||||||
|
//
|
||||||
|
// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b))
|
||||||
|
func Sprintln(a ...interface{}) string {
|
||||||
|
return fmt.Sprintln(convertArgs(a)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// convertArgs accepts a slice of arguments and returns a slice of the same
|
||||||
|
// length with each argument converted to a default spew Formatter interface.
|
||||||
|
func convertArgs(args []interface{}) (formatters []interface{}) {
|
||||||
|
formatters = make([]interface{}, len(args))
|
||||||
|
for index, arg := range args {
|
||||||
|
formatters[index] = NewFormatter(arg)
|
||||||
|
}
|
||||||
|
return formatters
|
||||||
|
}
|
||||||
309
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew_test.go
generated
vendored
Normal file
309
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,309 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 Dave Collins <dave@davec.name>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package spew_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
)
|
||||||
|
|
||||||
|
// spewFunc is used to identify which public function of the spew package or
|
||||||
|
// ConfigState a test applies to.
|
||||||
|
type spewFunc int
|
||||||
|
|
||||||
|
const (
|
||||||
|
fCSFdump spewFunc = iota
|
||||||
|
fCSFprint
|
||||||
|
fCSFprintf
|
||||||
|
fCSFprintln
|
||||||
|
fCSPrint
|
||||||
|
fCSPrintln
|
||||||
|
fCSSdump
|
||||||
|
fCSSprint
|
||||||
|
fCSSprintf
|
||||||
|
fCSSprintln
|
||||||
|
fCSErrorf
|
||||||
|
fCSNewFormatter
|
||||||
|
fErrorf
|
||||||
|
fFprint
|
||||||
|
fFprintln
|
||||||
|
fPrint
|
||||||
|
fPrintln
|
||||||
|
fSdump
|
||||||
|
fSprint
|
||||||
|
fSprintf
|
||||||
|
fSprintln
|
||||||
|
)
|
||||||
|
|
||||||
|
// Map of spewFunc values to names for pretty printing.
|
||||||
|
var spewFuncStrings = map[spewFunc]string{
|
||||||
|
fCSFdump: "ConfigState.Fdump",
|
||||||
|
fCSFprint: "ConfigState.Fprint",
|
||||||
|
fCSFprintf: "ConfigState.Fprintf",
|
||||||
|
fCSFprintln: "ConfigState.Fprintln",
|
||||||
|
fCSSdump: "ConfigState.Sdump",
|
||||||
|
fCSPrint: "ConfigState.Print",
|
||||||
|
fCSPrintln: "ConfigState.Println",
|
||||||
|
fCSSprint: "ConfigState.Sprint",
|
||||||
|
fCSSprintf: "ConfigState.Sprintf",
|
||||||
|
fCSSprintln: "ConfigState.Sprintln",
|
||||||
|
fCSErrorf: "ConfigState.Errorf",
|
||||||
|
fCSNewFormatter: "ConfigState.NewFormatter",
|
||||||
|
fErrorf: "spew.Errorf",
|
||||||
|
fFprint: "spew.Fprint",
|
||||||
|
fFprintln: "spew.Fprintln",
|
||||||
|
fPrint: "spew.Print",
|
||||||
|
fPrintln: "spew.Println",
|
||||||
|
fSdump: "spew.Sdump",
|
||||||
|
fSprint: "spew.Sprint",
|
||||||
|
fSprintf: "spew.Sprintf",
|
||||||
|
fSprintln: "spew.Sprintln",
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f spewFunc) String() string {
|
||||||
|
if s, ok := spewFuncStrings[f]; ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Unknown spewFunc (%d)", int(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
// spewTest is used to describe a test to be performed against the public
|
||||||
|
// functions of the spew package or ConfigState.
|
||||||
|
type spewTest struct {
|
||||||
|
cs *spew.ConfigState
|
||||||
|
f spewFunc
|
||||||
|
format string
|
||||||
|
in interface{}
|
||||||
|
want string
|
||||||
|
}
|
||||||
|
|
||||||
|
// spewTests houses the tests to be performed against the public functions of
|
||||||
|
// the spew package and ConfigState.
|
||||||
|
//
|
||||||
|
// These tests are only intended to ensure the public functions are exercised
|
||||||
|
// and are intentionally not exhaustive of types. The exhaustive type
|
||||||
|
// tests are handled in the dump and format tests.
|
||||||
|
var spewTests []spewTest
|
||||||
|
|
||||||
|
// redirStdout is a helper function to return the standard output from f as a
|
||||||
|
// byte slice.
|
||||||
|
func redirStdout(f func()) ([]byte, error) {
|
||||||
|
tempFile, err := ioutil.TempFile("", "ss-test")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fileName := tempFile.Name()
|
||||||
|
defer os.Remove(fileName) // Ignore error
|
||||||
|
|
||||||
|
origStdout := os.Stdout
|
||||||
|
os.Stdout = tempFile
|
||||||
|
f()
|
||||||
|
os.Stdout = origStdout
|
||||||
|
tempFile.Close()
|
||||||
|
|
||||||
|
return ioutil.ReadFile(fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initSpewTests() {
|
||||||
|
// Config states with various settings.
|
||||||
|
scsDefault := spew.NewDefaultConfig()
|
||||||
|
scsNoMethods := &spew.ConfigState{Indent: " ", DisableMethods: true}
|
||||||
|
scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true}
|
||||||
|
scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1}
|
||||||
|
scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true}
|
||||||
|
|
||||||
|
// Variables for tests on types which implement Stringer interface with and
|
||||||
|
// without a pointer receiver.
|
||||||
|
ts := stringer("test")
|
||||||
|
tps := pstringer("test")
|
||||||
|
|
||||||
|
// depthTester is used to test max depth handling for structs, array, slices
|
||||||
|
// and maps.
|
||||||
|
type depthTester struct {
|
||||||
|
ic indirCir1
|
||||||
|
arr [1]string
|
||||||
|
slice []string
|
||||||
|
m map[string]int
|
||||||
|
}
|
||||||
|
dt := depthTester{indirCir1{nil}, [1]string{"arr"}, []string{"slice"},
|
||||||
|
map[string]int{"one": 1}}
|
||||||
|
|
||||||
|
// Variable for tests on types which implement error interface.
|
||||||
|
te := customError(10)
|
||||||
|
|
||||||
|
spewTests = []spewTest{
|
||||||
|
{scsDefault, fCSFdump, "", int8(127), "(int8) 127\n"},
|
||||||
|
{scsDefault, fCSFprint, "", int16(32767), "32767"},
|
||||||
|
{scsDefault, fCSFprintf, "%v", int32(2147483647), "2147483647"},
|
||||||
|
{scsDefault, fCSFprintln, "", int(2147483647), "2147483647\n"},
|
||||||
|
{scsDefault, fCSPrint, "", int64(9223372036854775807), "9223372036854775807"},
|
||||||
|
{scsDefault, fCSPrintln, "", uint8(255), "255\n"},
|
||||||
|
{scsDefault, fCSSdump, "", uint8(64), "(uint8) 64\n"},
|
||||||
|
{scsDefault, fCSSprint, "", complex(1, 2), "(1+2i)"},
|
||||||
|
{scsDefault, fCSSprintf, "%v", complex(float32(3), 4), "(3+4i)"},
|
||||||
|
{scsDefault, fCSSprintln, "", complex(float64(5), 6), "(5+6i)\n"},
|
||||||
|
{scsDefault, fCSErrorf, "%#v", uint16(65535), "(uint16)65535"},
|
||||||
|
{scsDefault, fCSNewFormatter, "%v", uint32(4294967295), "4294967295"},
|
||||||
|
{scsDefault, fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"},
|
||||||
|
{scsDefault, fFprint, "", float32(3.14), "3.14"},
|
||||||
|
{scsDefault, fFprintln, "", float64(6.28), "6.28\n"},
|
||||||
|
{scsDefault, fPrint, "", true, "true"},
|
||||||
|
{scsDefault, fPrintln, "", false, "false\n"},
|
||||||
|
{scsDefault, fSdump, "", complex(-10, -20), "(complex128) (-10-20i)\n"},
|
||||||
|
{scsDefault, fSprint, "", complex(-1, -2), "(-1-2i)"},
|
||||||
|
{scsDefault, fSprintf, "%v", complex(float32(-3), -4), "(-3-4i)"},
|
||||||
|
{scsDefault, fSprintln, "", complex(float64(-5), -6), "(-5-6i)\n"},
|
||||||
|
{scsNoMethods, fCSFprint, "", ts, "test"},
|
||||||
|
{scsNoMethods, fCSFprint, "", &ts, "<*>test"},
|
||||||
|
{scsNoMethods, fCSFprint, "", tps, "test"},
|
||||||
|
{scsNoMethods, fCSFprint, "", &tps, "<*>test"},
|
||||||
|
{scsNoPmethods, fCSFprint, "", ts, "stringer test"},
|
||||||
|
{scsNoPmethods, fCSFprint, "", &ts, "<*>stringer test"},
|
||||||
|
{scsNoPmethods, fCSFprint, "", tps, "test"},
|
||||||
|
{scsNoPmethods, fCSFprint, "", &tps, "<*>stringer test"},
|
||||||
|
{scsMaxDepth, fCSFprint, "", dt, "{{<max>} [<max>] [<max>] map[<max>]}"},
|
||||||
|
{scsMaxDepth, fCSFdump, "", dt, "(spew_test.depthTester) {\n" +
|
||||||
|
" ic: (spew_test.indirCir1) {\n <max depth reached>\n },\n" +
|
||||||
|
" arr: ([1]string) (len=1 cap=1) {\n <max depth reached>\n },\n" +
|
||||||
|
" slice: ([]string) (len=1 cap=1) {\n <max depth reached>\n },\n" +
|
||||||
|
" m: (map[string]int) (len=1) {\n <max depth reached>\n }\n}\n"},
|
||||||
|
{scsContinue, fCSFprint, "", ts, "(stringer test) test"},
|
||||||
|
{scsContinue, fCSFdump, "", ts, "(spew_test.stringer) " +
|
||||||
|
"(len=4) (stringer test) \"test\"\n"},
|
||||||
|
{scsContinue, fCSFprint, "", te, "(error: 10) 10"},
|
||||||
|
{scsContinue, fCSFdump, "", te, "(spew_test.customError) " +
|
||||||
|
"(error: 10) 10\n"},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestSpew executes all of the tests described by spewTests.
|
||||||
|
func TestSpew(t *testing.T) {
|
||||||
|
initSpewTests()
|
||||||
|
|
||||||
|
t.Logf("Running %d tests", len(spewTests))
|
||||||
|
for i, test := range spewTests {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
switch test.f {
|
||||||
|
case fCSFdump:
|
||||||
|
test.cs.Fdump(buf, test.in)
|
||||||
|
|
||||||
|
case fCSFprint:
|
||||||
|
test.cs.Fprint(buf, test.in)
|
||||||
|
|
||||||
|
case fCSFprintf:
|
||||||
|
test.cs.Fprintf(buf, test.format, test.in)
|
||||||
|
|
||||||
|
case fCSFprintln:
|
||||||
|
test.cs.Fprintln(buf, test.in)
|
||||||
|
|
||||||
|
case fCSPrint:
|
||||||
|
b, err := redirStdout(func() { test.cs.Print(test.in) })
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%v #%d %v", test.f, i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
buf.Write(b)
|
||||||
|
|
||||||
|
case fCSPrintln:
|
||||||
|
b, err := redirStdout(func() { test.cs.Println(test.in) })
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%v #%d %v", test.f, i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
buf.Write(b)
|
||||||
|
|
||||||
|
case fCSSdump:
|
||||||
|
str := test.cs.Sdump(test.in)
|
||||||
|
buf.WriteString(str)
|
||||||
|
|
||||||
|
case fCSSprint:
|
||||||
|
str := test.cs.Sprint(test.in)
|
||||||
|
buf.WriteString(str)
|
||||||
|
|
||||||
|
case fCSSprintf:
|
||||||
|
str := test.cs.Sprintf(test.format, test.in)
|
||||||
|
buf.WriteString(str)
|
||||||
|
|
||||||
|
case fCSSprintln:
|
||||||
|
str := test.cs.Sprintln(test.in)
|
||||||
|
buf.WriteString(str)
|
||||||
|
|
||||||
|
case fCSErrorf:
|
||||||
|
err := test.cs.Errorf(test.format, test.in)
|
||||||
|
buf.WriteString(err.Error())
|
||||||
|
|
||||||
|
case fCSNewFormatter:
|
||||||
|
fmt.Fprintf(buf, test.format, test.cs.NewFormatter(test.in))
|
||||||
|
|
||||||
|
case fErrorf:
|
||||||
|
err := spew.Errorf(test.format, test.in)
|
||||||
|
buf.WriteString(err.Error())
|
||||||
|
|
||||||
|
case fFprint:
|
||||||
|
spew.Fprint(buf, test.in)
|
||||||
|
|
||||||
|
case fFprintln:
|
||||||
|
spew.Fprintln(buf, test.in)
|
||||||
|
|
||||||
|
case fPrint:
|
||||||
|
b, err := redirStdout(func() { spew.Print(test.in) })
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%v #%d %v", test.f, i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
buf.Write(b)
|
||||||
|
|
||||||
|
case fPrintln:
|
||||||
|
b, err := redirStdout(func() { spew.Println(test.in) })
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%v #%d %v", test.f, i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
buf.Write(b)
|
||||||
|
|
||||||
|
case fSdump:
|
||||||
|
str := spew.Sdump(test.in)
|
||||||
|
buf.WriteString(str)
|
||||||
|
|
||||||
|
case fSprint:
|
||||||
|
str := spew.Sprint(test.in)
|
||||||
|
buf.WriteString(str)
|
||||||
|
|
||||||
|
case fSprintf:
|
||||||
|
str := spew.Sprintf(test.format, test.in)
|
||||||
|
buf.WriteString(str)
|
||||||
|
|
||||||
|
case fSprintln:
|
||||||
|
str := spew.Sprintln(test.in)
|
||||||
|
buf.WriteString(str)
|
||||||
|
|
||||||
|
default:
|
||||||
|
t.Errorf("%v #%d unrecognized function", test.f, i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s := buf.String()
|
||||||
|
if test.want != s {
|
||||||
|
t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
Godeps/_workspace/src/github.com/docker/docker/pkg/units/duration_test.go
generated
vendored
46
Godeps/_workspace/src/github.com/docker/docker/pkg/units/duration_test.go
generated
vendored
|
|
@ -1,46 +0,0 @@
|
||||||
package units
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestHumanDuration(t *testing.T) {
|
|
||||||
// Useful duration abstractions
|
|
||||||
day := 24 * time.Hour
|
|
||||||
week := 7 * day
|
|
||||||
month := 30 * day
|
|
||||||
year := 365 * day
|
|
||||||
|
|
||||||
assertEquals(t, "Less than a second", HumanDuration(450*time.Millisecond))
|
|
||||||
assertEquals(t, "47 seconds", HumanDuration(47*time.Second))
|
|
||||||
assertEquals(t, "About a minute", HumanDuration(1*time.Minute))
|
|
||||||
assertEquals(t, "3 minutes", HumanDuration(3*time.Minute))
|
|
||||||
assertEquals(t, "35 minutes", HumanDuration(35*time.Minute))
|
|
||||||
assertEquals(t, "35 minutes", HumanDuration(35*time.Minute+40*time.Second))
|
|
||||||
assertEquals(t, "About an hour", HumanDuration(1*time.Hour))
|
|
||||||
assertEquals(t, "About an hour", HumanDuration(1*time.Hour+45*time.Minute))
|
|
||||||
assertEquals(t, "3 hours", HumanDuration(3*time.Hour))
|
|
||||||
assertEquals(t, "3 hours", HumanDuration(3*time.Hour+59*time.Minute))
|
|
||||||
assertEquals(t, "4 hours", HumanDuration(3*time.Hour+60*time.Minute))
|
|
||||||
assertEquals(t, "24 hours", HumanDuration(24*time.Hour))
|
|
||||||
assertEquals(t, "36 hours", HumanDuration(1*day+12*time.Hour))
|
|
||||||
assertEquals(t, "2 days", HumanDuration(2*day))
|
|
||||||
assertEquals(t, "7 days", HumanDuration(7*day))
|
|
||||||
assertEquals(t, "13 days", HumanDuration(13*day+5*time.Hour))
|
|
||||||
assertEquals(t, "2 weeks", HumanDuration(2*week))
|
|
||||||
assertEquals(t, "2 weeks", HumanDuration(2*week+4*day))
|
|
||||||
assertEquals(t, "3 weeks", HumanDuration(3*week))
|
|
||||||
assertEquals(t, "4 weeks", HumanDuration(4*week))
|
|
||||||
assertEquals(t, "4 weeks", HumanDuration(4*week+3*day))
|
|
||||||
assertEquals(t, "4 weeks", HumanDuration(1*month))
|
|
||||||
assertEquals(t, "6 weeks", HumanDuration(1*month+2*week))
|
|
||||||
assertEquals(t, "8 weeks", HumanDuration(2*month))
|
|
||||||
assertEquals(t, "3 months", HumanDuration(3*month+1*week))
|
|
||||||
assertEquals(t, "5 months", HumanDuration(5*month+2*week))
|
|
||||||
assertEquals(t, "13 months", HumanDuration(13*month))
|
|
||||||
assertEquals(t, "23 months", HumanDuration(23*month))
|
|
||||||
assertEquals(t, "24 months", HumanDuration(24*month))
|
|
||||||
assertEquals(t, "2 years", HumanDuration(24*month+2*week))
|
|
||||||
assertEquals(t, "3 years", HumanDuration(3*year+2*month))
|
|
||||||
}
|
|
||||||
108
Godeps/_workspace/src/github.com/docker/docker/pkg/units/size_test.go
generated
vendored
108
Godeps/_workspace/src/github.com/docker/docker/pkg/units/size_test.go
generated
vendored
|
|
@ -1,108 +0,0 @@
|
||||||
package units
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBytesSize(t *testing.T) {
|
|
||||||
assertEquals(t, "1 KiB", BytesSize(1024))
|
|
||||||
assertEquals(t, "1 MiB", BytesSize(1024*1024))
|
|
||||||
assertEquals(t, "1 MiB", BytesSize(1048576))
|
|
||||||
assertEquals(t, "2 MiB", BytesSize(2*MiB))
|
|
||||||
assertEquals(t, "3.42 GiB", BytesSize(3.42*GiB))
|
|
||||||
assertEquals(t, "5.372 TiB", BytesSize(5.372*TiB))
|
|
||||||
assertEquals(t, "2.22 PiB", BytesSize(2.22*PiB))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHumanSize(t *testing.T) {
|
|
||||||
assertEquals(t, "1 kB", HumanSize(1000))
|
|
||||||
assertEquals(t, "1.024 kB", HumanSize(1024))
|
|
||||||
assertEquals(t, "1 MB", HumanSize(1000000))
|
|
||||||
assertEquals(t, "1.049 MB", HumanSize(1048576))
|
|
||||||
assertEquals(t, "2 MB", HumanSize(2*MB))
|
|
||||||
assertEquals(t, "3.42 GB", HumanSize(float64(3.42*GB)))
|
|
||||||
assertEquals(t, "5.372 TB", HumanSize(float64(5.372*TB)))
|
|
||||||
assertEquals(t, "2.22 PB", HumanSize(float64(2.22*PB)))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFromHumanSize(t *testing.T) {
|
|
||||||
assertSuccessEquals(t, 32, FromHumanSize, "32")
|
|
||||||
assertSuccessEquals(t, 32, FromHumanSize, "32b")
|
|
||||||
assertSuccessEquals(t, 32, FromHumanSize, "32B")
|
|
||||||
assertSuccessEquals(t, 32*KB, FromHumanSize, "32k")
|
|
||||||
assertSuccessEquals(t, 32*KB, FromHumanSize, "32K")
|
|
||||||
assertSuccessEquals(t, 32*KB, FromHumanSize, "32kb")
|
|
||||||
assertSuccessEquals(t, 32*KB, FromHumanSize, "32Kb")
|
|
||||||
assertSuccessEquals(t, 32*MB, FromHumanSize, "32Mb")
|
|
||||||
assertSuccessEquals(t, 32*GB, FromHumanSize, "32Gb")
|
|
||||||
assertSuccessEquals(t, 32*TB, FromHumanSize, "32Tb")
|
|
||||||
assertSuccessEquals(t, 32*PB, FromHumanSize, "32Pb")
|
|
||||||
|
|
||||||
assertError(t, FromHumanSize, "")
|
|
||||||
assertError(t, FromHumanSize, "hello")
|
|
||||||
assertError(t, FromHumanSize, "-32")
|
|
||||||
assertError(t, FromHumanSize, "32.3")
|
|
||||||
assertError(t, FromHumanSize, " 32 ")
|
|
||||||
assertError(t, FromHumanSize, "32.3Kb")
|
|
||||||
assertError(t, FromHumanSize, "32 mb")
|
|
||||||
assertError(t, FromHumanSize, "32m b")
|
|
||||||
assertError(t, FromHumanSize, "32bm")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRAMInBytes(t *testing.T) {
|
|
||||||
assertSuccessEquals(t, 32, RAMInBytes, "32")
|
|
||||||
assertSuccessEquals(t, 32, RAMInBytes, "32b")
|
|
||||||
assertSuccessEquals(t, 32, RAMInBytes, "32B")
|
|
||||||
assertSuccessEquals(t, 32*KiB, RAMInBytes, "32k")
|
|
||||||
assertSuccessEquals(t, 32*KiB, RAMInBytes, "32K")
|
|
||||||
assertSuccessEquals(t, 32*KiB, RAMInBytes, "32kb")
|
|
||||||
assertSuccessEquals(t, 32*KiB, RAMInBytes, "32Kb")
|
|
||||||
assertSuccessEquals(t, 32*MiB, RAMInBytes, "32Mb")
|
|
||||||
assertSuccessEquals(t, 32*GiB, RAMInBytes, "32Gb")
|
|
||||||
assertSuccessEquals(t, 32*TiB, RAMInBytes, "32Tb")
|
|
||||||
assertSuccessEquals(t, 32*PiB, RAMInBytes, "32Pb")
|
|
||||||
assertSuccessEquals(t, 32*PiB, RAMInBytes, "32PB")
|
|
||||||
assertSuccessEquals(t, 32*PiB, RAMInBytes, "32P")
|
|
||||||
|
|
||||||
assertError(t, RAMInBytes, "")
|
|
||||||
assertError(t, RAMInBytes, "hello")
|
|
||||||
assertError(t, RAMInBytes, "-32")
|
|
||||||
assertError(t, RAMInBytes, "32.3")
|
|
||||||
assertError(t, RAMInBytes, " 32 ")
|
|
||||||
assertError(t, RAMInBytes, "32.3Kb")
|
|
||||||
assertError(t, RAMInBytes, "32 mb")
|
|
||||||
assertError(t, RAMInBytes, "32m b")
|
|
||||||
assertError(t, RAMInBytes, "32bm")
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertEquals(t *testing.T, expected, actual interface{}) {
|
|
||||||
if expected != actual {
|
|
||||||
t.Errorf("Expected '%v' but got '%v'", expected, actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// func that maps to the parse function signatures as testing abstraction
|
|
||||||
type parseFn func(string) (int64, error)
|
|
||||||
|
|
||||||
// Define 'String()' for pretty-print
|
|
||||||
func (fn parseFn) String() string {
|
|
||||||
fnName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
|
|
||||||
return fnName[strings.LastIndex(fnName, ".")+1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg string) {
|
|
||||||
res, err := fn(arg)
|
|
||||||
if err != nil || res != expected {
|
|
||||||
t.Errorf("%s(\"%s\") -> expected '%d' but got '%d' with error '%v'", fn, arg, expected, res, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertError(t *testing.T, fn parseFn, arg string) {
|
|
||||||
res, err := fn(arg)
|
|
||||||
if err == nil && res != -1 {
|
|
||||||
t.Errorf("%s(\"%s\") -> expected error but got '%d'", fn, arg, res)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
67
Godeps/_workspace/src/github.com/docker/go-units/CONTRIBUTING.md
generated
vendored
Normal file
67
Godeps/_workspace/src/github.com/docker/go-units/CONTRIBUTING.md
generated
vendored
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
# Contributing to go-units
|
||||||
|
|
||||||
|
Want to hack on go-units? Awesome! Here are instructions to get you started.
|
||||||
|
|
||||||
|
go-units is a part of the [Docker](https://www.docker.com) project, and follows
|
||||||
|
the same rules and principles. If you're already familiar with the way
|
||||||
|
Docker does things, you'll feel right at home.
|
||||||
|
|
||||||
|
Otherwise, go read Docker's
|
||||||
|
[contributions guidelines](https://github.com/docker/docker/blob/master/CONTRIBUTING.md),
|
||||||
|
[issue triaging](https://github.com/docker/docker/blob/master/project/ISSUE-TRIAGE.md),
|
||||||
|
[review process](https://github.com/docker/docker/blob/master/project/REVIEWING.md) and
|
||||||
|
[branches and tags](https://github.com/docker/docker/blob/master/project/BRANCHES-AND-TAGS.md).
|
||||||
|
|
||||||
|
### Sign your work
|
||||||
|
|
||||||
|
The sign-off is a simple line at the end of the explanation for the patch. Your
|
||||||
|
signature certifies that you wrote the patch or otherwise have the right to pass
|
||||||
|
it on as an open-source patch. The rules are pretty simple: if you can certify
|
||||||
|
the below (from [developercertificate.org](http://developercertificate.org/)):
|
||||||
|
|
||||||
|
```
|
||||||
|
Developer Certificate of Origin
|
||||||
|
Version 1.1
|
||||||
|
|
||||||
|
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
|
||||||
|
660 York Street, Suite 102,
|
||||||
|
San Francisco, CA 94110 USA
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies of this
|
||||||
|
license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Developer's Certificate of Origin 1.1
|
||||||
|
|
||||||
|
By making a contribution to this project, I certify that:
|
||||||
|
|
||||||
|
(a) The contribution was created in whole or in part by me and I
|
||||||
|
have the right to submit it under the open source license
|
||||||
|
indicated in the file; or
|
||||||
|
|
||||||
|
(b) The contribution is based upon previous work that, to the best
|
||||||
|
of my knowledge, is covered under an appropriate open source
|
||||||
|
license and I have the right under that license to submit that
|
||||||
|
work with modifications, whether created in whole or in part
|
||||||
|
by me, under the same open source license (unless I am
|
||||||
|
permitted to submit under a different license), as indicated
|
||||||
|
in the file; or
|
||||||
|
|
||||||
|
(c) The contribution was provided directly to me by some other
|
||||||
|
person who certified (a), (b) or (c) and I have not modified
|
||||||
|
it.
|
||||||
|
|
||||||
|
(d) I understand and agree that this project and the contribution
|
||||||
|
are public and that a record of the contribution (including all
|
||||||
|
personal information I submit with it, including my sign-off) is
|
||||||
|
maintained indefinitely and may be redistributed consistent with
|
||||||
|
this project or the open source license(s) involved.
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you just add a line to every git commit message:
|
||||||
|
|
||||||
|
Signed-off-by: Joe Smith <joe.smith@email.com>
|
||||||
|
|
||||||
|
Use your real name (sorry, no pseudonyms or anonymous contributions.)
|
||||||
|
|
||||||
|
If you set your `user.name` and `user.email` git configs, you can sign your
|
||||||
|
commit automatically with `git commit -s`.
|
||||||
191
Godeps/_workspace/src/github.com/docker/go-units/LICENSE.code
generated
vendored
Normal file
191
Godeps/_workspace/src/github.com/docker/go-units/LICENSE.code
generated
vendored
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
https://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
Copyright 2015 Docker, Inc.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
https://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.
|
||||||
425
Godeps/_workspace/src/github.com/docker/go-units/LICENSE.docs
generated
vendored
Normal file
425
Godeps/_workspace/src/github.com/docker/go-units/LICENSE.docs
generated
vendored
Normal file
|
|
@ -0,0 +1,425 @@
|
||||||
|
Attribution-ShareAlike 4.0 International
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||||
|
does not provide legal services or legal advice. Distribution of
|
||||||
|
Creative Commons public licenses does not create a lawyer-client or
|
||||||
|
other relationship. Creative Commons makes its licenses and related
|
||||||
|
information available on an "as-is" basis. Creative Commons gives no
|
||||||
|
warranties regarding its licenses, any material licensed under their
|
||||||
|
terms and conditions, or any related information. Creative Commons
|
||||||
|
disclaims all liability for damages resulting from their use to the
|
||||||
|
fullest extent possible.
|
||||||
|
|
||||||
|
Using Creative Commons Public Licenses
|
||||||
|
|
||||||
|
Creative Commons public licenses provide a standard set of terms and
|
||||||
|
conditions that creators and other rights holders may use to share
|
||||||
|
original works of authorship and other material subject to copyright
|
||||||
|
and certain other rights specified in the public license below. The
|
||||||
|
following considerations are for informational purposes only, are not
|
||||||
|
exhaustive, and do not form part of our licenses.
|
||||||
|
|
||||||
|
Considerations for licensors: Our public licenses are
|
||||||
|
intended for use by those authorized to give the public
|
||||||
|
permission to use material in ways otherwise restricted by
|
||||||
|
copyright and certain other rights. Our licenses are
|
||||||
|
irrevocable. Licensors should read and understand the terms
|
||||||
|
and conditions of the license they choose before applying it.
|
||||||
|
Licensors should also secure all rights necessary before
|
||||||
|
applying our licenses so that the public can reuse the
|
||||||
|
material as expected. Licensors should clearly mark any
|
||||||
|
material not subject to the license. This includes other CC-
|
||||||
|
licensed material, or material used under an exception or
|
||||||
|
limitation to copyright. More considerations for licensors:
|
||||||
|
wiki.creativecommons.org/Considerations_for_licensors
|
||||||
|
|
||||||
|
Considerations for the public: By using one of our public
|
||||||
|
licenses, a licensor grants the public permission to use the
|
||||||
|
licensed material under specified terms and conditions. If
|
||||||
|
the licensor's permission is not necessary for any reason--for
|
||||||
|
example, because of any applicable exception or limitation to
|
||||||
|
copyright--then that use is not regulated by the license. Our
|
||||||
|
licenses grant only permissions under copyright and certain
|
||||||
|
other rights that a licensor has authority to grant. Use of
|
||||||
|
the licensed material may still be restricted for other
|
||||||
|
reasons, including because others have copyright or other
|
||||||
|
rights in the material. A licensor may make special requests,
|
||||||
|
such as asking that all changes be marked or described.
|
||||||
|
Although not required by our licenses, you are encouraged to
|
||||||
|
respect those requests where reasonable. More_considerations
|
||||||
|
for the public:
|
||||||
|
wiki.creativecommons.org/Considerations_for_licensees
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons Attribution-ShareAlike 4.0 International Public
|
||||||
|
License
|
||||||
|
|
||||||
|
By exercising the Licensed Rights (defined below), You accept and agree
|
||||||
|
to be bound by the terms and conditions of this Creative Commons
|
||||||
|
Attribution-ShareAlike 4.0 International Public License ("Public
|
||||||
|
License"). To the extent this Public License may be interpreted as a
|
||||||
|
contract, You are granted the Licensed Rights in consideration of Your
|
||||||
|
acceptance of these terms and conditions, and the Licensor grants You
|
||||||
|
such rights in consideration of benefits the Licensor receives from
|
||||||
|
making the Licensed Material available under these terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
|
||||||
|
Section 1 -- Definitions.
|
||||||
|
|
||||||
|
a. Adapted Material means material subject to Copyright and Similar
|
||||||
|
Rights that is derived from or based upon the Licensed Material
|
||||||
|
and in which the Licensed Material is translated, altered,
|
||||||
|
arranged, transformed, or otherwise modified in a manner requiring
|
||||||
|
permission under the Copyright and Similar Rights held by the
|
||||||
|
Licensor. For purposes of this Public License, where the Licensed
|
||||||
|
Material is a musical work, performance, or sound recording,
|
||||||
|
Adapted Material is always produced where the Licensed Material is
|
||||||
|
synched in timed relation with a moving image.
|
||||||
|
|
||||||
|
b. Adapter's License means the license You apply to Your Copyright
|
||||||
|
and Similar Rights in Your contributions to Adapted Material in
|
||||||
|
accordance with the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
c. BY-SA Compatible License means a license listed at
|
||||||
|
creativecommons.org/compatiblelicenses, approved by Creative
|
||||||
|
Commons as essentially the equivalent of this Public License.
|
||||||
|
|
||||||
|
d. Copyright and Similar Rights means copyright and/or similar rights
|
||||||
|
closely related to copyright including, without limitation,
|
||||||
|
performance, broadcast, sound recording, and Sui Generis Database
|
||||||
|
Rights, without regard to how the rights are labeled or
|
||||||
|
categorized. For purposes of this Public License, the rights
|
||||||
|
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||||
|
Rights.
|
||||||
|
|
||||||
|
e. Effective Technological Measures means those measures that, in the
|
||||||
|
absence of proper authority, may not be circumvented under laws
|
||||||
|
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||||
|
Treaty adopted on December 20, 1996, and/or similar international
|
||||||
|
agreements.
|
||||||
|
|
||||||
|
f. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||||
|
any other exception or limitation to Copyright and Similar Rights
|
||||||
|
that applies to Your use of the Licensed Material.
|
||||||
|
|
||||||
|
g. License Elements means the license attributes listed in the name
|
||||||
|
of a Creative Commons Public License. The License Elements of this
|
||||||
|
Public License are Attribution and ShareAlike.
|
||||||
|
|
||||||
|
h. Licensed Material means the artistic or literary work, database,
|
||||||
|
or other material to which the Licensor applied this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
i. Licensed Rights means the rights granted to You subject to the
|
||||||
|
terms and conditions of this Public License, which are limited to
|
||||||
|
all Copyright and Similar Rights that apply to Your use of the
|
||||||
|
Licensed Material and that the Licensor has authority to license.
|
||||||
|
|
||||||
|
j. Licensor means the individual(s) or entity(ies) granting rights
|
||||||
|
under this Public License.
|
||||||
|
|
||||||
|
k. Share means to provide material to the public by any means or
|
||||||
|
process that requires permission under the Licensed Rights, such
|
||||||
|
as reproduction, public display, public performance, distribution,
|
||||||
|
dissemination, communication, or importation, and to make material
|
||||||
|
available to the public including in ways that members of the
|
||||||
|
public may access the material from a place and at a time
|
||||||
|
individually chosen by them.
|
||||||
|
|
||||||
|
l. Sui Generis Database Rights means rights other than copyright
|
||||||
|
resulting from Directive 96/9/EC of the European Parliament and of
|
||||||
|
the Council of 11 March 1996 on the legal protection of databases,
|
||||||
|
as amended and/or succeeded, as well as other essentially
|
||||||
|
equivalent rights anywhere in the world.
|
||||||
|
|
||||||
|
m. You means the individual or entity exercising the Licensed Rights
|
||||||
|
under this Public License. Your has a corresponding meaning.
|
||||||
|
|
||||||
|
|
||||||
|
Section 2 -- Scope.
|
||||||
|
|
||||||
|
a. License grant.
|
||||||
|
|
||||||
|
1. Subject to the terms and conditions of this Public License,
|
||||||
|
the Licensor hereby grants You a worldwide, royalty-free,
|
||||||
|
non-sublicensable, non-exclusive, irrevocable license to
|
||||||
|
exercise the Licensed Rights in the Licensed Material to:
|
||||||
|
|
||||||
|
a. reproduce and Share the Licensed Material, in whole or
|
||||||
|
in part; and
|
||||||
|
|
||||||
|
b. produce, reproduce, and Share Adapted Material.
|
||||||
|
|
||||||
|
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||||
|
Exceptions and Limitations apply to Your use, this Public
|
||||||
|
License does not apply, and You do not need to comply with
|
||||||
|
its terms and conditions.
|
||||||
|
|
||||||
|
3. Term. The term of this Public License is specified in Section
|
||||||
|
6(a).
|
||||||
|
|
||||||
|
4. Media and formats; technical modifications allowed. The
|
||||||
|
Licensor authorizes You to exercise the Licensed Rights in
|
||||||
|
all media and formats whether now known or hereafter created,
|
||||||
|
and to make technical modifications necessary to do so. The
|
||||||
|
Licensor waives and/or agrees not to assert any right or
|
||||||
|
authority to forbid You from making technical modifications
|
||||||
|
necessary to exercise the Licensed Rights, including
|
||||||
|
technical modifications necessary to circumvent Effective
|
||||||
|
Technological Measures. For purposes of this Public License,
|
||||||
|
simply making modifications authorized by this Section 2(a)
|
||||||
|
(4) never produces Adapted Material.
|
||||||
|
|
||||||
|
5. Downstream recipients.
|
||||||
|
|
||||||
|
a. Offer from the Licensor -- Licensed Material. Every
|
||||||
|
recipient of the Licensed Material automatically
|
||||||
|
receives an offer from the Licensor to exercise the
|
||||||
|
Licensed Rights under the terms and conditions of this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
b. Additional offer from the Licensor -- Adapted Material.
|
||||||
|
Every recipient of Adapted Material from You
|
||||||
|
automatically receives an offer from the Licensor to
|
||||||
|
exercise the Licensed Rights in the Adapted Material
|
||||||
|
under the conditions of the Adapter's License You apply.
|
||||||
|
|
||||||
|
c. No downstream restrictions. You may not offer or impose
|
||||||
|
any additional or different terms or conditions on, or
|
||||||
|
apply any Effective Technological Measures to, the
|
||||||
|
Licensed Material if doing so restricts exercise of the
|
||||||
|
Licensed Rights by any recipient of the Licensed
|
||||||
|
Material.
|
||||||
|
|
||||||
|
6. No endorsement. Nothing in this Public License constitutes or
|
||||||
|
may be construed as permission to assert or imply that You
|
||||||
|
are, or that Your use of the Licensed Material is, connected
|
||||||
|
with, or sponsored, endorsed, or granted official status by,
|
||||||
|
the Licensor or others designated to receive attribution as
|
||||||
|
provided in Section 3(a)(1)(A)(i).
|
||||||
|
|
||||||
|
b. Other rights.
|
||||||
|
|
||||||
|
1. Moral rights, such as the right of integrity, are not
|
||||||
|
licensed under this Public License, nor are publicity,
|
||||||
|
privacy, and/or other similar personality rights; however, to
|
||||||
|
the extent possible, the Licensor waives and/or agrees not to
|
||||||
|
assert any such rights held by the Licensor to the limited
|
||||||
|
extent necessary to allow You to exercise the Licensed
|
||||||
|
Rights, but not otherwise.
|
||||||
|
|
||||||
|
2. Patent and trademark rights are not licensed under this
|
||||||
|
Public License.
|
||||||
|
|
||||||
|
3. To the extent possible, the Licensor waives any right to
|
||||||
|
collect royalties from You for the exercise of the Licensed
|
||||||
|
Rights, whether directly or through a collecting society
|
||||||
|
under any voluntary or waivable statutory or compulsory
|
||||||
|
licensing scheme. In all other cases the Licensor expressly
|
||||||
|
reserves any right to collect such royalties.
|
||||||
|
|
||||||
|
|
||||||
|
Section 3 -- License Conditions.
|
||||||
|
|
||||||
|
Your exercise of the Licensed Rights is expressly made subject to the
|
||||||
|
following conditions.
|
||||||
|
|
||||||
|
a. Attribution.
|
||||||
|
|
||||||
|
1. If You Share the Licensed Material (including in modified
|
||||||
|
form), You must:
|
||||||
|
|
||||||
|
a. retain the following if it is supplied by the Licensor
|
||||||
|
with the Licensed Material:
|
||||||
|
|
||||||
|
i. identification of the creator(s) of the Licensed
|
||||||
|
Material and any others designated to receive
|
||||||
|
attribution, in any reasonable manner requested by
|
||||||
|
the Licensor (including by pseudonym if
|
||||||
|
designated);
|
||||||
|
|
||||||
|
ii. a copyright notice;
|
||||||
|
|
||||||
|
iii. a notice that refers to this Public License;
|
||||||
|
|
||||||
|
iv. a notice that refers to the disclaimer of
|
||||||
|
warranties;
|
||||||
|
|
||||||
|
v. a URI or hyperlink to the Licensed Material to the
|
||||||
|
extent reasonably practicable;
|
||||||
|
|
||||||
|
b. indicate if You modified the Licensed Material and
|
||||||
|
retain an indication of any previous modifications; and
|
||||||
|
|
||||||
|
c. indicate the Licensed Material is licensed under this
|
||||||
|
Public License, and include the text of, or the URI or
|
||||||
|
hyperlink to, this Public License.
|
||||||
|
|
||||||
|
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||||
|
reasonable manner based on the medium, means, and context in
|
||||||
|
which You Share the Licensed Material. For example, it may be
|
||||||
|
reasonable to satisfy the conditions by providing a URI or
|
||||||
|
hyperlink to a resource that includes the required
|
||||||
|
information.
|
||||||
|
|
||||||
|
3. If requested by the Licensor, You must remove any of the
|
||||||
|
information required by Section 3(a)(1)(A) to the extent
|
||||||
|
reasonably practicable.
|
||||||
|
|
||||||
|
b. ShareAlike.
|
||||||
|
|
||||||
|
In addition to the conditions in Section 3(a), if You Share
|
||||||
|
Adapted Material You produce, the following conditions also apply.
|
||||||
|
|
||||||
|
1. The Adapter's License You apply must be a Creative Commons
|
||||||
|
license with the same License Elements, this version or
|
||||||
|
later, or a BY-SA Compatible License.
|
||||||
|
|
||||||
|
2. You must include the text of, or the URI or hyperlink to, the
|
||||||
|
Adapter's License You apply. You may satisfy this condition
|
||||||
|
in any reasonable manner based on the medium, means, and
|
||||||
|
context in which You Share Adapted Material.
|
||||||
|
|
||||||
|
3. You may not offer or impose any additional or different terms
|
||||||
|
or conditions on, or apply any Effective Technological
|
||||||
|
Measures to, Adapted Material that restrict exercise of the
|
||||||
|
rights granted under the Adapter's License You apply.
|
||||||
|
|
||||||
|
|
||||||
|
Section 4 -- Sui Generis Database Rights.
|
||||||
|
|
||||||
|
Where the Licensed Rights include Sui Generis Database Rights that
|
||||||
|
apply to Your use of the Licensed Material:
|
||||||
|
|
||||||
|
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||||
|
to extract, reuse, reproduce, and Share all or a substantial
|
||||||
|
portion of the contents of the database;
|
||||||
|
|
||||||
|
b. if You include all or a substantial portion of the database
|
||||||
|
contents in a database in which You have Sui Generis Database
|
||||||
|
Rights, then the database in which You have Sui Generis Database
|
||||||
|
Rights (but not its individual contents) is Adapted Material,
|
||||||
|
|
||||||
|
including for purposes of Section 3(b); and
|
||||||
|
c. You must comply with the conditions in Section 3(a) if You Share
|
||||||
|
all or a substantial portion of the contents of the database.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 4 supplements and does not
|
||||||
|
replace Your obligations under this Public License where the Licensed
|
||||||
|
Rights include other Copyright and Similar Rights.
|
||||||
|
|
||||||
|
|
||||||
|
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||||
|
|
||||||
|
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||||
|
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||||
|
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||||
|
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||||
|
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||||
|
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||||
|
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||||
|
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||||
|
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||||
|
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||||
|
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||||
|
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||||
|
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||||
|
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||||
|
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||||
|
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||||
|
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||||
|
|
||||||
|
c. The disclaimer of warranties and limitation of liability provided
|
||||||
|
above shall be interpreted in a manner that, to the extent
|
||||||
|
possible, most closely approximates an absolute disclaimer and
|
||||||
|
waiver of all liability.
|
||||||
|
|
||||||
|
|
||||||
|
Section 6 -- Term and Termination.
|
||||||
|
|
||||||
|
a. This Public License applies for the term of the Copyright and
|
||||||
|
Similar Rights licensed here. However, if You fail to comply with
|
||||||
|
this Public License, then Your rights under this Public License
|
||||||
|
terminate automatically.
|
||||||
|
|
||||||
|
b. Where Your right to use the Licensed Material has terminated under
|
||||||
|
Section 6(a), it reinstates:
|
||||||
|
|
||||||
|
1. automatically as of the date the violation is cured, provided
|
||||||
|
it is cured within 30 days of Your discovery of the
|
||||||
|
violation; or
|
||||||
|
|
||||||
|
2. upon express reinstatement by the Licensor.
|
||||||
|
|
||||||
|
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||||
|
right the Licensor may have to seek remedies for Your violations
|
||||||
|
of this Public License.
|
||||||
|
|
||||||
|
c. For the avoidance of doubt, the Licensor may also offer the
|
||||||
|
Licensed Material under separate terms or conditions or stop
|
||||||
|
distributing the Licensed Material at any time; however, doing so
|
||||||
|
will not terminate this Public License.
|
||||||
|
|
||||||
|
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||||
|
License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 7 -- Other Terms and Conditions.
|
||||||
|
|
||||||
|
a. The Licensor shall not be bound by any additional or different
|
||||||
|
terms or conditions communicated by You unless expressly agreed.
|
||||||
|
|
||||||
|
b. Any arrangements, understandings, or agreements regarding the
|
||||||
|
Licensed Material not stated herein are separate from and
|
||||||
|
independent of the terms and conditions of this Public License.
|
||||||
|
|
||||||
|
|
||||||
|
Section 8 -- Interpretation.
|
||||||
|
|
||||||
|
a. For the avoidance of doubt, this Public License does not, and
|
||||||
|
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||||
|
conditions on any use of the Licensed Material that could lawfully
|
||||||
|
be made without permission under this Public License.
|
||||||
|
|
||||||
|
b. To the extent possible, if any provision of this Public License is
|
||||||
|
deemed unenforceable, it shall be automatically reformed to the
|
||||||
|
minimum extent necessary to make it enforceable. If the provision
|
||||||
|
cannot be reformed, it shall be severed from this Public License
|
||||||
|
without affecting the enforceability of the remaining terms and
|
||||||
|
conditions.
|
||||||
|
|
||||||
|
c. No term or condition of this Public License will be waived and no
|
||||||
|
failure to comply consented to unless expressly agreed to by the
|
||||||
|
Licensor.
|
||||||
|
|
||||||
|
d. Nothing in this Public License constitutes or may be interpreted
|
||||||
|
as a limitation upon, or waiver of, any privileges and immunities
|
||||||
|
that apply to the Licensor or You, including from the legal
|
||||||
|
processes of any jurisdiction or authority.
|
||||||
|
|
||||||
|
|
||||||
|
=======================================================================
|
||||||
|
|
||||||
|
Creative Commons is not a party to its public licenses.
|
||||||
|
Notwithstanding, Creative Commons may elect to apply one of its public
|
||||||
|
licenses to material it publishes and in those instances will be
|
||||||
|
considered the "Licensor." Except for the limited purpose of indicating
|
||||||
|
that material is shared under a Creative Commons public license or as
|
||||||
|
otherwise permitted by the Creative Commons policies published at
|
||||||
|
creativecommons.org/policies, Creative Commons does not authorize the
|
||||||
|
use of the trademark "Creative Commons" or any other trademark or logo
|
||||||
|
of Creative Commons without its prior written consent including,
|
||||||
|
without limitation, in connection with any unauthorized modifications
|
||||||
|
to any of its public licenses or any other arrangements,
|
||||||
|
understandings, or agreements concerning use of licensed material. For
|
||||||
|
the avoidance of doubt, this paragraph does not form part of the public
|
||||||
|
licenses.
|
||||||
|
|
||||||
|
Creative Commons may be contacted at creativecommons.org.
|
||||||
27
Godeps/_workspace/src/github.com/docker/go-units/MAINTAINERS
generated
vendored
Normal file
27
Godeps/_workspace/src/github.com/docker/go-units/MAINTAINERS
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# go-connections maintainers file
|
||||||
|
#
|
||||||
|
# This file describes who runs the docker/go-connections project and how.
|
||||||
|
# This is a living document - if you see something out of date or missing, speak up!
|
||||||
|
#
|
||||||
|
# It is structured to be consumable by both humans and programs.
|
||||||
|
# To extract its contents programmatically, use any TOML-compliant parser.
|
||||||
|
#
|
||||||
|
# This file is compiled into the MAINTAINERS file in docker/opensource.
|
||||||
|
#
|
||||||
|
[Org]
|
||||||
|
[Org."Core maintainers"]
|
||||||
|
people = [
|
||||||
|
"calavera",
|
||||||
|
]
|
||||||
|
|
||||||
|
[people]
|
||||||
|
|
||||||
|
# A reference list of all people associated with the project.
|
||||||
|
# All other sections should refer to people by their canonical key
|
||||||
|
# in the people section.
|
||||||
|
|
||||||
|
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
|
||||||
|
[people.calavera]
|
||||||
|
Name = "David Calavera"
|
||||||
|
Email = "david.calavera@gmail.com"
|
||||||
|
GitHub = "calavera"
|
||||||
18
Godeps/_workspace/src/github.com/docker/go-units/README.md
generated
vendored
Normal file
18
Godeps/_workspace/src/github.com/docker/go-units/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
[](https://godoc.org/github.com/docker/go-units)
|
||||||
|
|
||||||
|
# Introduction
|
||||||
|
|
||||||
|
go-units is a library to transform human friendly measurements into machine friendly values.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
See the [docs in godoc](https://godoc.org/github.com/docker/go-units) for examples and documentation.
|
||||||
|
|
||||||
|
## Copyright and license
|
||||||
|
|
||||||
|
Copyright © 2015 Docker, Inc. All rights reserved, except as follows. Code
|
||||||
|
is released under the Apache 2.0 license. The README.md file, and files in the
|
||||||
|
"docs" folder are licensed under the Creative Commons Attribution 4.0
|
||||||
|
International License under the terms and conditions set forth in the file
|
||||||
|
"LICENSE.docs". You may obtain a duplicate copy of the same license, titled
|
||||||
|
CC-BY-SA-4.0, at http://creativecommons.org/licenses/by/4.0/.
|
||||||
11
Godeps/_workspace/src/github.com/docker/go-units/circle.yml
generated
vendored
Normal file
11
Godeps/_workspace/src/github.com/docker/go-units/circle.yml
generated
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
dependencies:
|
||||||
|
post:
|
||||||
|
# install golint
|
||||||
|
- go get github.com/golang/lint/golint
|
||||||
|
|
||||||
|
test:
|
||||||
|
pre:
|
||||||
|
# run analysis before tests
|
||||||
|
- go vet ./...
|
||||||
|
- test -z "$(golint ./... | tee /dev/stderr)"
|
||||||
|
- test -z "$(gofmt -s -l . | tee /dev/stderr)"
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
// Package units provides helper function to parse and print size and time units
|
||||||
|
// in human-readable format.
|
||||||
package units
|
package units
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -6,7 +8,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// HumanDuration returns a human-readable approximation of a duration
|
// HumanDuration returns a human-readable approximation of a duration
|
||||||
// (eg. "About a minute", "4 hours ago", etc.)
|
// (eg. "About a minute", "4 hours ago", etc.).
|
||||||
func HumanDuration(d time.Duration) string {
|
func HumanDuration(d time.Duration) string {
|
||||||
if seconds := int(d.Seconds()); seconds < 1 {
|
if seconds := int(d.Seconds()); seconds < 1 {
|
||||||
return "Less than a second"
|
return "Less than a second"
|
||||||
|
|
@ -31,14 +31,14 @@ type unitMap map[string]int64
|
||||||
var (
|
var (
|
||||||
decimalMap = unitMap{"k": KB, "m": MB, "g": GB, "t": TB, "p": PB}
|
decimalMap = unitMap{"k": KB, "m": MB, "g": GB, "t": TB, "p": PB}
|
||||||
binaryMap = unitMap{"k": KiB, "m": MiB, "g": GiB, "t": TiB, "p": PiB}
|
binaryMap = unitMap{"k": KiB, "m": MiB, "g": GiB, "t": TiB, "p": PiB}
|
||||||
sizeRegex = regexp.MustCompile(`^(\d+)([kKmMgGtTpP])?[bB]?$`)
|
sizeRegex = regexp.MustCompile(`^(\d+(\.\d+)*) ?([kKmMgGtTpP])?[bB]?$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
var decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
var decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
||||||
var binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
|
var binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
|
||||||
|
|
||||||
// CustomSize returns a human-readable approximation of a size
|
// CustomSize returns a human-readable approximation of a size
|
||||||
// using custom format
|
// using custom format.
|
||||||
func CustomSize(format string, size float64, base float64, _map []string) string {
|
func CustomSize(format string, size float64, base float64, _map []string) string {
|
||||||
i := 0
|
i := 0
|
||||||
for size >= base {
|
for size >= base {
|
||||||
|
|
@ -49,17 +49,19 @@ func CustomSize(format string, size float64, base float64, _map []string) string
|
||||||
}
|
}
|
||||||
|
|
||||||
// HumanSize returns a human-readable approximation of a size
|
// HumanSize returns a human-readable approximation of a size
|
||||||
// using SI standard (eg. "44kB", "17MB")
|
// capped at 4 valid numbers (eg. "2.746 MB", "796 KB").
|
||||||
func HumanSize(size float64) string {
|
func HumanSize(size float64) string {
|
||||||
return CustomSize("%.4g %s", size, 1000.0, decimapAbbrs)
|
return CustomSize("%.4g %s", size, 1000.0, decimapAbbrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BytesSize returns a human-readable size in bytes, kibibytes,
|
||||||
|
// mebibytes, gibibytes, or tebibytes (eg. "44kiB", "17MiB").
|
||||||
func BytesSize(size float64) string {
|
func BytesSize(size float64) string {
|
||||||
return CustomSize("%.4g %s", size, 1024.0, binaryAbbrs)
|
return CustomSize("%.4g %s", size, 1024.0, binaryAbbrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromHumanSize returns an integer from a human-readable specification of a
|
// FromHumanSize returns an integer from a human-readable specification of a
|
||||||
// size using SI standard (eg. "44kB", "17MB")
|
// size using SI standard (eg. "44kB", "17MB").
|
||||||
func FromHumanSize(size string) (int64, error) {
|
func FromHumanSize(size string) (int64, error) {
|
||||||
return parseSize(size, decimalMap)
|
return parseSize(size, decimalMap)
|
||||||
}
|
}
|
||||||
|
|
@ -72,22 +74,22 @@ func RAMInBytes(size string) (int64, error) {
|
||||||
return parseSize(size, binaryMap)
|
return parseSize(size, binaryMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses the human-readable size string into the amount it represents
|
// Parses the human-readable size string into the amount it represents.
|
||||||
func parseSize(sizeStr string, uMap unitMap) (int64, error) {
|
func parseSize(sizeStr string, uMap unitMap) (int64, error) {
|
||||||
matches := sizeRegex.FindStringSubmatch(sizeStr)
|
matches := sizeRegex.FindStringSubmatch(sizeStr)
|
||||||
if len(matches) != 3 {
|
if len(matches) != 4 {
|
||||||
return -1, fmt.Errorf("invalid size: '%s'", sizeStr)
|
return -1, fmt.Errorf("invalid size: '%s'", sizeStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
size, err := strconv.ParseInt(matches[1], 10, 0)
|
size, err := strconv.ParseFloat(matches[1], 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
unitPrefix := strings.ToLower(matches[2])
|
unitPrefix := strings.ToLower(matches[3])
|
||||||
if mul, ok := uMap[unitPrefix]; ok {
|
if mul, ok := uMap[unitPrefix]; ok {
|
||||||
size *= mul
|
size *= float64(mul)
|
||||||
}
|
}
|
||||||
|
|
||||||
return size, nil
|
return int64(size), nil
|
||||||
}
|
}
|
||||||
118
Godeps/_workspace/src/github.com/docker/go-units/ulimit.go
generated
vendored
Normal file
118
Godeps/_workspace/src/github.com/docker/go-units/ulimit.go
generated
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
package units
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Ulimit is a human friendly version of Rlimit.
|
||||||
|
type Ulimit struct {
|
||||||
|
Name string
|
||||||
|
Hard int64
|
||||||
|
Soft int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rlimit specifies the resource limits, such as max open files.
|
||||||
|
type Rlimit struct {
|
||||||
|
Type int `json:"type,omitempty"`
|
||||||
|
Hard uint64 `json:"hard,omitempty"`
|
||||||
|
Soft uint64 `json:"soft,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// magic numbers for making the syscall
|
||||||
|
// some of these are defined in the syscall package, but not all.
|
||||||
|
// Also since Windows client doesn't get access to the syscall package, need to
|
||||||
|
// define these here
|
||||||
|
rlimitAs = 9
|
||||||
|
rlimitCore = 4
|
||||||
|
rlimitCPU = 0
|
||||||
|
rlimitData = 2
|
||||||
|
rlimitFsize = 1
|
||||||
|
rlimitLocks = 10
|
||||||
|
rlimitMemlock = 8
|
||||||
|
rlimitMsgqueue = 12
|
||||||
|
rlimitNice = 13
|
||||||
|
rlimitNofile = 7
|
||||||
|
rlimitNproc = 6
|
||||||
|
rlimitRss = 5
|
||||||
|
rlimitRtprio = 14
|
||||||
|
rlimitRttime = 15
|
||||||
|
rlimitSigpending = 11
|
||||||
|
rlimitStack = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
var ulimitNameMapping = map[string]int{
|
||||||
|
//"as": rlimitAs, // Disabled since this doesn't seem usable with the way Docker inits a container.
|
||||||
|
"core": rlimitCore,
|
||||||
|
"cpu": rlimitCPU,
|
||||||
|
"data": rlimitData,
|
||||||
|
"fsize": rlimitFsize,
|
||||||
|
"locks": rlimitLocks,
|
||||||
|
"memlock": rlimitMemlock,
|
||||||
|
"msgqueue": rlimitMsgqueue,
|
||||||
|
"nice": rlimitNice,
|
||||||
|
"nofile": rlimitNofile,
|
||||||
|
"nproc": rlimitNproc,
|
||||||
|
"rss": rlimitRss,
|
||||||
|
"rtprio": rlimitRtprio,
|
||||||
|
"rttime": rlimitRttime,
|
||||||
|
"sigpending": rlimitSigpending,
|
||||||
|
"stack": rlimitStack,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseUlimit parses and returns a Ulimit from the specified string.
|
||||||
|
func ParseUlimit(val string) (*Ulimit, error) {
|
||||||
|
parts := strings.SplitN(val, "=", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return nil, fmt.Errorf("invalid ulimit argument: %s", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, exists := ulimitNameMapping[parts[0]]; !exists {
|
||||||
|
return nil, fmt.Errorf("invalid ulimit type: %s", parts[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
soft int64
|
||||||
|
hard = &soft // default to soft in case no hard was set
|
||||||
|
temp int64
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
switch limitVals := strings.Split(parts[1], ":"); len(limitVals) {
|
||||||
|
case 2:
|
||||||
|
temp, err = strconv.ParseInt(limitVals[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
hard = &temp
|
||||||
|
fallthrough
|
||||||
|
case 1:
|
||||||
|
soft, err = strconv.ParseInt(limitVals[0], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("too many limit value arguments - %s, can only have up to two, `soft[:hard]`", parts[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
if soft > *hard {
|
||||||
|
return nil, fmt.Errorf("ulimit soft limit must be less than or equal to hard limit: %d > %d", soft, *hard)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Ulimit{Name: parts[0], Soft: soft, Hard: *hard}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRlimit returns the RLimit corresponding to Ulimit.
|
||||||
|
func (u *Ulimit) GetRlimit() (*Rlimit, error) {
|
||||||
|
t, exists := ulimitNameMapping[u.Name]
|
||||||
|
if !exists {
|
||||||
|
return nil, fmt.Errorf("invalid ulimit name %s", u.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Rlimit{Type: t, Soft: uint64(u.Soft), Hard: uint64(u.Hard)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Ulimit) String() string {
|
||||||
|
return fmt.Sprintf("%s=%d:%d", u.Name, u.Soft, u.Hard)
|
||||||
|
}
|
||||||
27
Godeps/_workspace/src/github.com/pmezard/go-difflib/LICENSE
generated
vendored
Normal file
27
Godeps/_workspace/src/github.com/pmezard/go-difflib/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
Copyright (c) 2013, Patrick Mezard
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
The names of its contributors may not be used to endorse or promote
|
||||||
|
products derived from this software without specific prior written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||||
|
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
772
Godeps/_workspace/src/github.com/pmezard/go-difflib/difflib/difflib.go
generated
vendored
Normal file
772
Godeps/_workspace/src/github.com/pmezard/go-difflib/difflib/difflib.go
generated
vendored
Normal file
|
|
@ -0,0 +1,772 @@
|
||||||
|
// Package difflib is a partial port of Python difflib module.
|
||||||
|
//
|
||||||
|
// It provides tools to compare sequences of strings and generate textual diffs.
|
||||||
|
//
|
||||||
|
// The following class and functions have been ported:
|
||||||
|
//
|
||||||
|
// - SequenceMatcher
|
||||||
|
//
|
||||||
|
// - unified_diff
|
||||||
|
//
|
||||||
|
// - context_diff
|
||||||
|
//
|
||||||
|
// Getting unified diffs was the main goal of the port. Keep in mind this code
|
||||||
|
// is mostly suitable to output text differences in a human friendly way, there
|
||||||
|
// are no guarantees generated diffs are consumable by patch(1).
|
||||||
|
package difflib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func min(a, b int) int {
|
||||||
|
if a < b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func max(a, b int) int {
|
||||||
|
if a > b {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func calculateRatio(matches, length int) float64 {
|
||||||
|
if length > 0 {
|
||||||
|
return 2.0 * float64(matches) / float64(length)
|
||||||
|
}
|
||||||
|
return 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
type Match struct {
|
||||||
|
A int
|
||||||
|
B int
|
||||||
|
Size int
|
||||||
|
}
|
||||||
|
|
||||||
|
type OpCode struct {
|
||||||
|
Tag byte
|
||||||
|
I1 int
|
||||||
|
I2 int
|
||||||
|
J1 int
|
||||||
|
J2 int
|
||||||
|
}
|
||||||
|
|
||||||
|
// SequenceMatcher compares sequence of strings. The basic
|
||||||
|
// algorithm predates, and is a little fancier than, an algorithm
|
||||||
|
// published in the late 1980's by Ratcliff and Obershelp under the
|
||||||
|
// hyperbolic name "gestalt pattern matching". The basic idea is to find
|
||||||
|
// the longest contiguous matching subsequence that contains no "junk"
|
||||||
|
// elements (R-O doesn't address junk). The same idea is then applied
|
||||||
|
// recursively to the pieces of the sequences to the left and to the right
|
||||||
|
// of the matching subsequence. This does not yield minimal edit
|
||||||
|
// sequences, but does tend to yield matches that "look right" to people.
|
||||||
|
//
|
||||||
|
// SequenceMatcher tries to compute a "human-friendly diff" between two
|
||||||
|
// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the
|
||||||
|
// longest *contiguous* & junk-free matching subsequence. That's what
|
||||||
|
// catches peoples' eyes. The Windows(tm) windiff has another interesting
|
||||||
|
// notion, pairing up elements that appear uniquely in each sequence.
|
||||||
|
// That, and the method here, appear to yield more intuitive difference
|
||||||
|
// reports than does diff. This method appears to be the least vulnerable
|
||||||
|
// to synching up on blocks of "junk lines", though (like blank lines in
|
||||||
|
// ordinary text files, or maybe "<P>" lines in HTML files). That may be
|
||||||
|
// because this is the only method of the 3 that has a *concept* of
|
||||||
|
// "junk" <wink>.
|
||||||
|
//
|
||||||
|
// Timing: Basic R-O is cubic time worst case and quadratic time expected
|
||||||
|
// case. SequenceMatcher is quadratic time for the worst case and has
|
||||||
|
// expected-case behavior dependent in a complicated way on how many
|
||||||
|
// elements the sequences have in common; best case time is linear.
|
||||||
|
type SequenceMatcher struct {
|
||||||
|
a []string
|
||||||
|
b []string
|
||||||
|
b2j map[string][]int
|
||||||
|
IsJunk func(string) bool
|
||||||
|
autoJunk bool
|
||||||
|
bJunk map[string]struct{}
|
||||||
|
matchingBlocks []Match
|
||||||
|
fullBCount map[string]int
|
||||||
|
bPopular map[string]struct{}
|
||||||
|
opCodes []OpCode
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMatcher(a, b []string) *SequenceMatcher {
|
||||||
|
m := SequenceMatcher{autoJunk: true}
|
||||||
|
m.SetSeqs(a, b)
|
||||||
|
return &m
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMatcherWithJunk(a, b []string, autoJunk bool,
|
||||||
|
isJunk func(string) bool) *SequenceMatcher {
|
||||||
|
|
||||||
|
m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk}
|
||||||
|
m.SetSeqs(a, b)
|
||||||
|
return &m
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set two sequences to be compared.
|
||||||
|
func (m *SequenceMatcher) SetSeqs(a, b []string) {
|
||||||
|
m.SetSeq1(a)
|
||||||
|
m.SetSeq2(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the first sequence to be compared. The second sequence to be compared is
|
||||||
|
// not changed.
|
||||||
|
//
|
||||||
|
// SequenceMatcher computes and caches detailed information about the second
|
||||||
|
// sequence, so if you want to compare one sequence S against many sequences,
|
||||||
|
// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other
|
||||||
|
// sequences.
|
||||||
|
//
|
||||||
|
// See also SetSeqs() and SetSeq2().
|
||||||
|
func (m *SequenceMatcher) SetSeq1(a []string) {
|
||||||
|
if &a == &m.a {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.a = a
|
||||||
|
m.matchingBlocks = nil
|
||||||
|
m.opCodes = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the second sequence to be compared. The first sequence to be compared is
|
||||||
|
// not changed.
|
||||||
|
func (m *SequenceMatcher) SetSeq2(b []string) {
|
||||||
|
if &b == &m.b {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m.b = b
|
||||||
|
m.matchingBlocks = nil
|
||||||
|
m.opCodes = nil
|
||||||
|
m.fullBCount = nil
|
||||||
|
m.chainB()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SequenceMatcher) chainB() {
|
||||||
|
// Populate line -> index mapping
|
||||||
|
b2j := map[string][]int{}
|
||||||
|
for i, s := range m.b {
|
||||||
|
indices := b2j[s]
|
||||||
|
indices = append(indices, i)
|
||||||
|
b2j[s] = indices
|
||||||
|
}
|
||||||
|
|
||||||
|
// Purge junk elements
|
||||||
|
m.bJunk = map[string]struct{}{}
|
||||||
|
if m.IsJunk != nil {
|
||||||
|
junk := m.bJunk
|
||||||
|
for s, _ := range b2j {
|
||||||
|
if m.IsJunk(s) {
|
||||||
|
junk[s] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for s, _ := range junk {
|
||||||
|
delete(b2j, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Purge remaining popular elements
|
||||||
|
popular := map[string]struct{}{}
|
||||||
|
n := len(m.b)
|
||||||
|
if m.autoJunk && n >= 200 {
|
||||||
|
ntest := n/100 + 1
|
||||||
|
for s, indices := range b2j {
|
||||||
|
if len(indices) > ntest {
|
||||||
|
popular[s] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for s, _ := range popular {
|
||||||
|
delete(b2j, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.bPopular = popular
|
||||||
|
m.b2j = b2j
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SequenceMatcher) isBJunk(s string) bool {
|
||||||
|
_, ok := m.bJunk[s]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find longest matching block in a[alo:ahi] and b[blo:bhi].
|
||||||
|
//
|
||||||
|
// If IsJunk is not defined:
|
||||||
|
//
|
||||||
|
// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where
|
||||||
|
// alo <= i <= i+k <= ahi
|
||||||
|
// blo <= j <= j+k <= bhi
|
||||||
|
// and for all (i',j',k') meeting those conditions,
|
||||||
|
// k >= k'
|
||||||
|
// i <= i'
|
||||||
|
// and if i == i', j <= j'
|
||||||
|
//
|
||||||
|
// In other words, of all maximal matching blocks, return one that
|
||||||
|
// starts earliest in a, and of all those maximal matching blocks that
|
||||||
|
// start earliest in a, return the one that starts earliest in b.
|
||||||
|
//
|
||||||
|
// If IsJunk is defined, first the longest matching block is
|
||||||
|
// determined as above, but with the additional restriction that no
|
||||||
|
// junk element appears in the block. Then that block is extended as
|
||||||
|
// far as possible by matching (only) junk elements on both sides. So
|
||||||
|
// the resulting block never matches on junk except as identical junk
|
||||||
|
// happens to be adjacent to an "interesting" match.
|
||||||
|
//
|
||||||
|
// If no blocks match, return (alo, blo, 0).
|
||||||
|
func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match {
|
||||||
|
// CAUTION: stripping common prefix or suffix would be incorrect.
|
||||||
|
// E.g.,
|
||||||
|
// ab
|
||||||
|
// acab
|
||||||
|
// Longest matching block is "ab", but if common prefix is
|
||||||
|
// stripped, it's "a" (tied with "b"). UNIX(tm) diff does so
|
||||||
|
// strip, so ends up claiming that ab is changed to acab by
|
||||||
|
// inserting "ca" in the middle. That's minimal but unintuitive:
|
||||||
|
// "it's obvious" that someone inserted "ac" at the front.
|
||||||
|
// Windiff ends up at the same place as diff, but by pairing up
|
||||||
|
// the unique 'b's and then matching the first two 'a's.
|
||||||
|
besti, bestj, bestsize := alo, blo, 0
|
||||||
|
|
||||||
|
// find longest junk-free match
|
||||||
|
// during an iteration of the loop, j2len[j] = length of longest
|
||||||
|
// junk-free match ending with a[i-1] and b[j]
|
||||||
|
j2len := map[int]int{}
|
||||||
|
for i := alo; i != ahi; i++ {
|
||||||
|
// look at all instances of a[i] in b; note that because
|
||||||
|
// b2j has no junk keys, the loop is skipped if a[i] is junk
|
||||||
|
newj2len := map[int]int{}
|
||||||
|
for _, j := range m.b2j[m.a[i]] {
|
||||||
|
// a[i] matches b[j]
|
||||||
|
if j < blo {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if j >= bhi {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
k := j2len[j-1] + 1
|
||||||
|
newj2len[j] = k
|
||||||
|
if k > bestsize {
|
||||||
|
besti, bestj, bestsize = i-k+1, j-k+1, k
|
||||||
|
}
|
||||||
|
}
|
||||||
|
j2len = newj2len
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extend the best by non-junk elements on each end. In particular,
|
||||||
|
// "popular" non-junk elements aren't in b2j, which greatly speeds
|
||||||
|
// the inner loop above, but also means "the best" match so far
|
||||||
|
// doesn't contain any junk *or* popular non-junk elements.
|
||||||
|
for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) &&
|
||||||
|
m.a[besti-1] == m.b[bestj-1] {
|
||||||
|
besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
|
||||||
|
}
|
||||||
|
for besti+bestsize < ahi && bestj+bestsize < bhi &&
|
||||||
|
!m.isBJunk(m.b[bestj+bestsize]) &&
|
||||||
|
m.a[besti+bestsize] == m.b[bestj+bestsize] {
|
||||||
|
bestsize += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that we have a wholly interesting match (albeit possibly
|
||||||
|
// empty!), we may as well suck up the matching junk on each
|
||||||
|
// side of it too. Can't think of a good reason not to, and it
|
||||||
|
// saves post-processing the (possibly considerable) expense of
|
||||||
|
// figuring out what to do with it. In the case of an empty
|
||||||
|
// interesting match, this is clearly the right thing to do,
|
||||||
|
// because no other kind of match is possible in the regions.
|
||||||
|
for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) &&
|
||||||
|
m.a[besti-1] == m.b[bestj-1] {
|
||||||
|
besti, bestj, bestsize = besti-1, bestj-1, bestsize+1
|
||||||
|
}
|
||||||
|
for besti+bestsize < ahi && bestj+bestsize < bhi &&
|
||||||
|
m.isBJunk(m.b[bestj+bestsize]) &&
|
||||||
|
m.a[besti+bestsize] == m.b[bestj+bestsize] {
|
||||||
|
bestsize += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return Match{A: besti, B: bestj, Size: bestsize}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return list of triples describing matching subsequences.
|
||||||
|
//
|
||||||
|
// Each triple is of the form (i, j, n), and means that
|
||||||
|
// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in
|
||||||
|
// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are
|
||||||
|
// adjacent triples in the list, and the second is not the last triple in the
|
||||||
|
// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe
|
||||||
|
// adjacent equal blocks.
|
||||||
|
//
|
||||||
|
// The last triple is a dummy, (len(a), len(b), 0), and is the only
|
||||||
|
// triple with n==0.
|
||||||
|
func (m *SequenceMatcher) GetMatchingBlocks() []Match {
|
||||||
|
if m.matchingBlocks != nil {
|
||||||
|
return m.matchingBlocks
|
||||||
|
}
|
||||||
|
|
||||||
|
var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match
|
||||||
|
matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match {
|
||||||
|
match := m.findLongestMatch(alo, ahi, blo, bhi)
|
||||||
|
i, j, k := match.A, match.B, match.Size
|
||||||
|
if match.Size > 0 {
|
||||||
|
if alo < i && blo < j {
|
||||||
|
matched = matchBlocks(alo, i, blo, j, matched)
|
||||||
|
}
|
||||||
|
matched = append(matched, match)
|
||||||
|
if i+k < ahi && j+k < bhi {
|
||||||
|
matched = matchBlocks(i+k, ahi, j+k, bhi, matched)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matched
|
||||||
|
}
|
||||||
|
matched := matchBlocks(0, len(m.a), 0, len(m.b), nil)
|
||||||
|
|
||||||
|
// It's possible that we have adjacent equal blocks in the
|
||||||
|
// matching_blocks list now.
|
||||||
|
nonAdjacent := []Match{}
|
||||||
|
i1, j1, k1 := 0, 0, 0
|
||||||
|
for _, b := range matched {
|
||||||
|
// Is this block adjacent to i1, j1, k1?
|
||||||
|
i2, j2, k2 := b.A, b.B, b.Size
|
||||||
|
if i1+k1 == i2 && j1+k1 == j2 {
|
||||||
|
// Yes, so collapse them -- this just increases the length of
|
||||||
|
// the first block by the length of the second, and the first
|
||||||
|
// block so lengthened remains the block to compare against.
|
||||||
|
k1 += k2
|
||||||
|
} else {
|
||||||
|
// Not adjacent. Remember the first block (k1==0 means it's
|
||||||
|
// the dummy we started with), and make the second block the
|
||||||
|
// new block to compare against.
|
||||||
|
if k1 > 0 {
|
||||||
|
nonAdjacent = append(nonAdjacent, Match{i1, j1, k1})
|
||||||
|
}
|
||||||
|
i1, j1, k1 = i2, j2, k2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if k1 > 0 {
|
||||||
|
nonAdjacent = append(nonAdjacent, Match{i1, j1, k1})
|
||||||
|
}
|
||||||
|
|
||||||
|
nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0})
|
||||||
|
m.matchingBlocks = nonAdjacent
|
||||||
|
return m.matchingBlocks
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return list of 5-tuples describing how to turn a into b.
|
||||||
|
//
|
||||||
|
// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple
|
||||||
|
// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the
|
||||||
|
// tuple preceding it, and likewise for j1 == the previous j2.
|
||||||
|
//
|
||||||
|
// The tags are characters, with these meanings:
|
||||||
|
//
|
||||||
|
// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2]
|
||||||
|
//
|
||||||
|
// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case.
|
||||||
|
//
|
||||||
|
// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case.
|
||||||
|
//
|
||||||
|
// 'e' (equal): a[i1:i2] == b[j1:j2]
|
||||||
|
func (m *SequenceMatcher) GetOpCodes() []OpCode {
|
||||||
|
if m.opCodes != nil {
|
||||||
|
return m.opCodes
|
||||||
|
}
|
||||||
|
i, j := 0, 0
|
||||||
|
matching := m.GetMatchingBlocks()
|
||||||
|
opCodes := make([]OpCode, 0, len(matching))
|
||||||
|
for _, m := range matching {
|
||||||
|
// invariant: we've pumped out correct diffs to change
|
||||||
|
// a[:i] into b[:j], and the next matching block is
|
||||||
|
// a[ai:ai+size] == b[bj:bj+size]. So we need to pump
|
||||||
|
// out a diff to change a[i:ai] into b[j:bj], pump out
|
||||||
|
// the matching block, and move (i,j) beyond the match
|
||||||
|
ai, bj, size := m.A, m.B, m.Size
|
||||||
|
tag := byte(0)
|
||||||
|
if i < ai && j < bj {
|
||||||
|
tag = 'r'
|
||||||
|
} else if i < ai {
|
||||||
|
tag = 'd'
|
||||||
|
} else if j < bj {
|
||||||
|
tag = 'i'
|
||||||
|
}
|
||||||
|
if tag > 0 {
|
||||||
|
opCodes = append(opCodes, OpCode{tag, i, ai, j, bj})
|
||||||
|
}
|
||||||
|
i, j = ai+size, bj+size
|
||||||
|
// the list of matching blocks is terminated by a
|
||||||
|
// sentinel with size 0
|
||||||
|
if size > 0 {
|
||||||
|
opCodes = append(opCodes, OpCode{'e', ai, i, bj, j})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.opCodes = opCodes
|
||||||
|
return m.opCodes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Isolate change clusters by eliminating ranges with no changes.
|
||||||
|
//
|
||||||
|
// Return a generator of groups with up to n lines of context.
|
||||||
|
// Each group is in the same format as returned by GetOpCodes().
|
||||||
|
func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode {
|
||||||
|
if n < 0 {
|
||||||
|
n = 3
|
||||||
|
}
|
||||||
|
codes := m.GetOpCodes()
|
||||||
|
if len(codes) == 0 {
|
||||||
|
codes = []OpCode{OpCode{'e', 0, 1, 0, 1}}
|
||||||
|
}
|
||||||
|
// Fixup leading and trailing groups if they show no changes.
|
||||||
|
if codes[0].Tag == 'e' {
|
||||||
|
c := codes[0]
|
||||||
|
i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
|
||||||
|
codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2}
|
||||||
|
}
|
||||||
|
if codes[len(codes)-1].Tag == 'e' {
|
||||||
|
c := codes[len(codes)-1]
|
||||||
|
i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
|
||||||
|
codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)}
|
||||||
|
}
|
||||||
|
nn := n + n
|
||||||
|
groups := [][]OpCode{}
|
||||||
|
group := []OpCode{}
|
||||||
|
for _, c := range codes {
|
||||||
|
i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
|
||||||
|
// End the current group and start a new one whenever
|
||||||
|
// there is a large range with no changes.
|
||||||
|
if c.Tag == 'e' && i2-i1 > nn {
|
||||||
|
group = append(group, OpCode{c.Tag, i1, min(i2, i1+n),
|
||||||
|
j1, min(j2, j1+n)})
|
||||||
|
groups = append(groups, group)
|
||||||
|
group = []OpCode{}
|
||||||
|
i1, j1 = max(i1, i2-n), max(j1, j2-n)
|
||||||
|
}
|
||||||
|
group = append(group, OpCode{c.Tag, i1, i2, j1, j2})
|
||||||
|
}
|
||||||
|
if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') {
|
||||||
|
groups = append(groups, group)
|
||||||
|
}
|
||||||
|
return groups
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a measure of the sequences' similarity (float in [0,1]).
|
||||||
|
//
|
||||||
|
// Where T is the total number of elements in both sequences, and
|
||||||
|
// M is the number of matches, this is 2.0*M / T.
|
||||||
|
// Note that this is 1 if the sequences are identical, and 0 if
|
||||||
|
// they have nothing in common.
|
||||||
|
//
|
||||||
|
// .Ratio() is expensive to compute if you haven't already computed
|
||||||
|
// .GetMatchingBlocks() or .GetOpCodes(), in which case you may
|
||||||
|
// want to try .QuickRatio() or .RealQuickRation() first to get an
|
||||||
|
// upper bound.
|
||||||
|
func (m *SequenceMatcher) Ratio() float64 {
|
||||||
|
matches := 0
|
||||||
|
for _, m := range m.GetMatchingBlocks() {
|
||||||
|
matches += m.Size
|
||||||
|
}
|
||||||
|
return calculateRatio(matches, len(m.a)+len(m.b))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an upper bound on ratio() relatively quickly.
|
||||||
|
//
|
||||||
|
// This isn't defined beyond that it is an upper bound on .Ratio(), and
|
||||||
|
// is faster to compute.
|
||||||
|
func (m *SequenceMatcher) QuickRatio() float64 {
|
||||||
|
// viewing a and b as multisets, set matches to the cardinality
|
||||||
|
// of their intersection; this counts the number of matches
|
||||||
|
// without regard to order, so is clearly an upper bound
|
||||||
|
if m.fullBCount == nil {
|
||||||
|
m.fullBCount = map[string]int{}
|
||||||
|
for _, s := range m.b {
|
||||||
|
m.fullBCount[s] = m.fullBCount[s] + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// avail[x] is the number of times x appears in 'b' less the
|
||||||
|
// number of times we've seen it in 'a' so far ... kinda
|
||||||
|
avail := map[string]int{}
|
||||||
|
matches := 0
|
||||||
|
for _, s := range m.a {
|
||||||
|
n, ok := avail[s]
|
||||||
|
if !ok {
|
||||||
|
n = m.fullBCount[s]
|
||||||
|
}
|
||||||
|
avail[s] = n - 1
|
||||||
|
if n > 0 {
|
||||||
|
matches += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return calculateRatio(matches, len(m.a)+len(m.b))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an upper bound on ratio() very quickly.
|
||||||
|
//
|
||||||
|
// This isn't defined beyond that it is an upper bound on .Ratio(), and
|
||||||
|
// is faster to compute than either .Ratio() or .QuickRatio().
|
||||||
|
func (m *SequenceMatcher) RealQuickRatio() float64 {
|
||||||
|
la, lb := len(m.a), len(m.b)
|
||||||
|
return calculateRatio(min(la, lb), la+lb)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert range to the "ed" format
|
||||||
|
func formatRangeUnified(start, stop int) string {
|
||||||
|
// Per the diff spec at http://www.unix.org/single_unix_specification/
|
||||||
|
beginning := start + 1 // lines start numbering with one
|
||||||
|
length := stop - start
|
||||||
|
if length == 1 {
|
||||||
|
return fmt.Sprintf("%d", beginning)
|
||||||
|
}
|
||||||
|
if length == 0 {
|
||||||
|
beginning -= 1 // empty ranges begin at line just before the range
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%d,%d", beginning, length)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unified diff parameters
|
||||||
|
type UnifiedDiff struct {
|
||||||
|
A []string // First sequence lines
|
||||||
|
FromFile string // First file name
|
||||||
|
FromDate string // First file time
|
||||||
|
B []string // Second sequence lines
|
||||||
|
ToFile string // Second file name
|
||||||
|
ToDate string // Second file time
|
||||||
|
Eol string // Headers end of line, defaults to LF
|
||||||
|
Context int // Number of context lines
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare two sequences of lines; generate the delta as a unified diff.
|
||||||
|
//
|
||||||
|
// Unified diffs are a compact way of showing line changes and a few
|
||||||
|
// lines of context. The number of context lines is set by 'n' which
|
||||||
|
// defaults to three.
|
||||||
|
//
|
||||||
|
// By default, the diff control lines (those with ---, +++, or @@) are
|
||||||
|
// created with a trailing newline. This is helpful so that inputs
|
||||||
|
// created from file.readlines() result in diffs that are suitable for
|
||||||
|
// file.writelines() since both the inputs and outputs have trailing
|
||||||
|
// newlines.
|
||||||
|
//
|
||||||
|
// For inputs that do not have trailing newlines, set the lineterm
|
||||||
|
// argument to "" so that the output will be uniformly newline free.
|
||||||
|
//
|
||||||
|
// The unidiff format normally has a header for filenames and modification
|
||||||
|
// times. Any or all of these may be specified using strings for
|
||||||
|
// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'.
|
||||||
|
// The modification times are normally expressed in the ISO 8601 format.
|
||||||
|
func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error {
|
||||||
|
buf := bufio.NewWriter(writer)
|
||||||
|
defer buf.Flush()
|
||||||
|
wf := func(format string, args ...interface{}) error {
|
||||||
|
_, err := buf.WriteString(fmt.Sprintf(format, args...))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ws := func(s string) error {
|
||||||
|
_, err := buf.WriteString(s)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(diff.Eol) == 0 {
|
||||||
|
diff.Eol = "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
started := false
|
||||||
|
m := NewMatcher(diff.A, diff.B)
|
||||||
|
for _, g := range m.GetGroupedOpCodes(diff.Context) {
|
||||||
|
if !started {
|
||||||
|
started = true
|
||||||
|
fromDate := ""
|
||||||
|
if len(diff.FromDate) > 0 {
|
||||||
|
fromDate = "\t" + diff.FromDate
|
||||||
|
}
|
||||||
|
toDate := ""
|
||||||
|
if len(diff.ToDate) > 0 {
|
||||||
|
toDate = "\t" + diff.ToDate
|
||||||
|
}
|
||||||
|
if diff.FromFile != "" || diff.ToFile != "" {
|
||||||
|
err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first, last := g[0], g[len(g)-1]
|
||||||
|
range1 := formatRangeUnified(first.I1, last.I2)
|
||||||
|
range2 := formatRangeUnified(first.J1, last.J2)
|
||||||
|
if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, c := range g {
|
||||||
|
i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2
|
||||||
|
if c.Tag == 'e' {
|
||||||
|
for _, line := range diff.A[i1:i2] {
|
||||||
|
if err := ws(" " + line); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if c.Tag == 'r' || c.Tag == 'd' {
|
||||||
|
for _, line := range diff.A[i1:i2] {
|
||||||
|
if err := ws("-" + line); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.Tag == 'r' || c.Tag == 'i' {
|
||||||
|
for _, line := range diff.B[j1:j2] {
|
||||||
|
if err := ws("+" + line); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Like WriteUnifiedDiff but returns the diff a string.
|
||||||
|
func GetUnifiedDiffString(diff UnifiedDiff) (string, error) {
|
||||||
|
w := &bytes.Buffer{}
|
||||||
|
err := WriteUnifiedDiff(w, diff)
|
||||||
|
return string(w.Bytes()), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert range to the "ed" format.
|
||||||
|
func formatRangeContext(start, stop int) string {
|
||||||
|
// Per the diff spec at http://www.unix.org/single_unix_specification/
|
||||||
|
beginning := start + 1 // lines start numbering with one
|
||||||
|
length := stop - start
|
||||||
|
if length == 0 {
|
||||||
|
beginning -= 1 // empty ranges begin at line just before the range
|
||||||
|
}
|
||||||
|
if length <= 1 {
|
||||||
|
return fmt.Sprintf("%d", beginning)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%d,%d", beginning, beginning+length-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ContextDiff UnifiedDiff
|
||||||
|
|
||||||
|
// Compare two sequences of lines; generate the delta as a context diff.
|
||||||
|
//
|
||||||
|
// Context diffs are a compact way of showing line changes and a few
|
||||||
|
// lines of context. The number of context lines is set by diff.Context
|
||||||
|
// which defaults to three.
|
||||||
|
//
|
||||||
|
// By default, the diff control lines (those with *** or ---) are
|
||||||
|
// created with a trailing newline.
|
||||||
|
//
|
||||||
|
// For inputs that do not have trailing newlines, set the diff.Eol
|
||||||
|
// argument to "" so that the output will be uniformly newline free.
|
||||||
|
//
|
||||||
|
// The context diff format normally has a header for filenames and
|
||||||
|
// modification times. Any or all of these may be specified using
|
||||||
|
// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate.
|
||||||
|
// The modification times are normally expressed in the ISO 8601 format.
|
||||||
|
// If not specified, the strings default to blanks.
|
||||||
|
func WriteContextDiff(writer io.Writer, diff ContextDiff) error {
|
||||||
|
buf := bufio.NewWriter(writer)
|
||||||
|
defer buf.Flush()
|
||||||
|
var diffErr error
|
||||||
|
wf := func(format string, args ...interface{}) {
|
||||||
|
_, err := buf.WriteString(fmt.Sprintf(format, args...))
|
||||||
|
if diffErr == nil && err != nil {
|
||||||
|
diffErr = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ws := func(s string) {
|
||||||
|
_, err := buf.WriteString(s)
|
||||||
|
if diffErr == nil && err != nil {
|
||||||
|
diffErr = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(diff.Eol) == 0 {
|
||||||
|
diff.Eol = "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix := map[byte]string{
|
||||||
|
'i': "+ ",
|
||||||
|
'd': "- ",
|
||||||
|
'r': "! ",
|
||||||
|
'e': " ",
|
||||||
|
}
|
||||||
|
|
||||||
|
started := false
|
||||||
|
m := NewMatcher(diff.A, diff.B)
|
||||||
|
for _, g := range m.GetGroupedOpCodes(diff.Context) {
|
||||||
|
if !started {
|
||||||
|
started = true
|
||||||
|
fromDate := ""
|
||||||
|
if len(diff.FromDate) > 0 {
|
||||||
|
fromDate = "\t" + diff.FromDate
|
||||||
|
}
|
||||||
|
toDate := ""
|
||||||
|
if len(diff.ToDate) > 0 {
|
||||||
|
toDate = "\t" + diff.ToDate
|
||||||
|
}
|
||||||
|
if diff.FromFile != "" || diff.ToFile != "" {
|
||||||
|
wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol)
|
||||||
|
wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
first, last := g[0], g[len(g)-1]
|
||||||
|
ws("***************" + diff.Eol)
|
||||||
|
|
||||||
|
range1 := formatRangeContext(first.I1, last.I2)
|
||||||
|
wf("*** %s ****%s", range1, diff.Eol)
|
||||||
|
for _, c := range g {
|
||||||
|
if c.Tag == 'r' || c.Tag == 'd' {
|
||||||
|
for _, cc := range g {
|
||||||
|
if cc.Tag == 'i' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, line := range diff.A[cc.I1:cc.I2] {
|
||||||
|
ws(prefix[cc.Tag] + line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
range2 := formatRangeContext(first.J1, last.J2)
|
||||||
|
wf("--- %s ----%s", range2, diff.Eol)
|
||||||
|
for _, c := range g {
|
||||||
|
if c.Tag == 'r' || c.Tag == 'i' {
|
||||||
|
for _, cc := range g {
|
||||||
|
if cc.Tag == 'd' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, line := range diff.B[cc.J1:cc.J2] {
|
||||||
|
ws(prefix[cc.Tag] + line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return diffErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Like WriteContextDiff but returns the diff a string.
|
||||||
|
func GetContextDiffString(diff ContextDiff) (string, error) {
|
||||||
|
w := &bytes.Buffer{}
|
||||||
|
err := WriteContextDiff(w, diff)
|
||||||
|
return string(w.Bytes()), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split a string on "\n" while preserving them. The output can be used
|
||||||
|
// as input for UnifiedDiff and ContextDiff structures.
|
||||||
|
func SplitLines(s string) []string {
|
||||||
|
lines := strings.SplitAfter(s, "\n")
|
||||||
|
lines[len(lines)-1] += "\n"
|
||||||
|
return lines
|
||||||
|
}
|
||||||
426
Godeps/_workspace/src/github.com/pmezard/go-difflib/difflib/difflib_test.go
generated
vendored
Normal file
426
Godeps/_workspace/src/github.com/pmezard/go-difflib/difflib/difflib_test.go
generated
vendored
Normal file
|
|
@ -0,0 +1,426 @@
|
||||||
|
package difflib
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func assertAlmostEqual(t *testing.T, a, b float64, places int) {
|
||||||
|
if math.Abs(a-b) > math.Pow10(-places) {
|
||||||
|
t.Errorf("%.7f != %.7f", a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertEqual(t *testing.T, a, b interface{}) {
|
||||||
|
if !reflect.DeepEqual(a, b) {
|
||||||
|
t.Errorf("%v != %v", a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitChars(s string) []string {
|
||||||
|
chars := make([]string, 0, len(s))
|
||||||
|
// Assume ASCII inputs
|
||||||
|
for i := 0; i != len(s); i++ {
|
||||||
|
chars = append(chars, string(s[i]))
|
||||||
|
}
|
||||||
|
return chars
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSequenceMatcherRatio(t *testing.T) {
|
||||||
|
s := NewMatcher(splitChars("abcd"), splitChars("bcde"))
|
||||||
|
assertEqual(t, s.Ratio(), 0.75)
|
||||||
|
assertEqual(t, s.QuickRatio(), 0.75)
|
||||||
|
assertEqual(t, s.RealQuickRatio(), 1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetOptCodes(t *testing.T) {
|
||||||
|
a := "qabxcd"
|
||||||
|
b := "abycdf"
|
||||||
|
s := NewMatcher(splitChars(a), splitChars(b))
|
||||||
|
w := &bytes.Buffer{}
|
||||||
|
for _, op := range s.GetOpCodes() {
|
||||||
|
fmt.Fprintf(w, "%s a[%d:%d], (%s) b[%d:%d] (%s)\n", string(op.Tag),
|
||||||
|
op.I1, op.I2, a[op.I1:op.I2], op.J1, op.J2, b[op.J1:op.J2])
|
||||||
|
}
|
||||||
|
result := string(w.Bytes())
|
||||||
|
expected := `d a[0:1], (q) b[0:0] ()
|
||||||
|
e a[1:3], (ab) b[0:2] (ab)
|
||||||
|
r a[3:4], (x) b[2:3] (y)
|
||||||
|
e a[4:6], (cd) b[3:5] (cd)
|
||||||
|
i a[6:6], () b[5:6] (f)
|
||||||
|
`
|
||||||
|
if expected != result {
|
||||||
|
t.Errorf("unexpected op codes: \n%s", result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGroupedOpCodes(t *testing.T) {
|
||||||
|
a := []string{}
|
||||||
|
for i := 0; i != 39; i++ {
|
||||||
|
a = append(a, fmt.Sprintf("%02d", i))
|
||||||
|
}
|
||||||
|
b := []string{}
|
||||||
|
b = append(b, a[:8]...)
|
||||||
|
b = append(b, " i")
|
||||||
|
b = append(b, a[8:19]...)
|
||||||
|
b = append(b, " x")
|
||||||
|
b = append(b, a[20:22]...)
|
||||||
|
b = append(b, a[27:34]...)
|
||||||
|
b = append(b, " y")
|
||||||
|
b = append(b, a[35:]...)
|
||||||
|
s := NewMatcher(a, b)
|
||||||
|
w := &bytes.Buffer{}
|
||||||
|
for _, g := range s.GetGroupedOpCodes(-1) {
|
||||||
|
fmt.Fprintf(w, "group\n")
|
||||||
|
for _, op := range g {
|
||||||
|
fmt.Fprintf(w, " %s, %d, %d, %d, %d\n", string(op.Tag),
|
||||||
|
op.I1, op.I2, op.J1, op.J2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result := string(w.Bytes())
|
||||||
|
expected := `group
|
||||||
|
e, 5, 8, 5, 8
|
||||||
|
i, 8, 8, 8, 9
|
||||||
|
e, 8, 11, 9, 12
|
||||||
|
group
|
||||||
|
e, 16, 19, 17, 20
|
||||||
|
r, 19, 20, 20, 21
|
||||||
|
e, 20, 22, 21, 23
|
||||||
|
d, 22, 27, 23, 23
|
||||||
|
e, 27, 30, 23, 26
|
||||||
|
group
|
||||||
|
e, 31, 34, 27, 30
|
||||||
|
r, 34, 35, 30, 31
|
||||||
|
e, 35, 38, 31, 34
|
||||||
|
`
|
||||||
|
if expected != result {
|
||||||
|
t.Errorf("unexpected op codes: \n%s", result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleGetUnifiedDiffCode() {
|
||||||
|
a := `one
|
||||||
|
two
|
||||||
|
three
|
||||||
|
four
|
||||||
|
fmt.Printf("%s,%T",a,b)`
|
||||||
|
b := `zero
|
||||||
|
one
|
||||||
|
three
|
||||||
|
four`
|
||||||
|
diff := UnifiedDiff{
|
||||||
|
A: SplitLines(a),
|
||||||
|
B: SplitLines(b),
|
||||||
|
FromFile: "Original",
|
||||||
|
FromDate: "2005-01-26 23:30:50",
|
||||||
|
ToFile: "Current",
|
||||||
|
ToDate: "2010-04-02 10:20:52",
|
||||||
|
Context: 3,
|
||||||
|
}
|
||||||
|
result, _ := GetUnifiedDiffString(diff)
|
||||||
|
fmt.Println(strings.Replace(result, "\t", " ", -1))
|
||||||
|
// Output:
|
||||||
|
// --- Original 2005-01-26 23:30:50
|
||||||
|
// +++ Current 2010-04-02 10:20:52
|
||||||
|
// @@ -1,5 +1,4 @@
|
||||||
|
// +zero
|
||||||
|
// one
|
||||||
|
// -two
|
||||||
|
// three
|
||||||
|
// four
|
||||||
|
// -fmt.Printf("%s,%T",a,b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleGetContextDiffCode() {
|
||||||
|
a := `one
|
||||||
|
two
|
||||||
|
three
|
||||||
|
four
|
||||||
|
fmt.Printf("%s,%T",a,b)`
|
||||||
|
b := `zero
|
||||||
|
one
|
||||||
|
tree
|
||||||
|
four`
|
||||||
|
diff := ContextDiff{
|
||||||
|
A: SplitLines(a),
|
||||||
|
B: SplitLines(b),
|
||||||
|
FromFile: "Original",
|
||||||
|
ToFile: "Current",
|
||||||
|
Context: 3,
|
||||||
|
Eol: "\n",
|
||||||
|
}
|
||||||
|
result, _ := GetContextDiffString(diff)
|
||||||
|
fmt.Print(strings.Replace(result, "\t", " ", -1))
|
||||||
|
// Output:
|
||||||
|
// *** Original
|
||||||
|
// --- Current
|
||||||
|
// ***************
|
||||||
|
// *** 1,5 ****
|
||||||
|
// one
|
||||||
|
// ! two
|
||||||
|
// ! three
|
||||||
|
// four
|
||||||
|
// - fmt.Printf("%s,%T",a,b)
|
||||||
|
// --- 1,4 ----
|
||||||
|
// + zero
|
||||||
|
// one
|
||||||
|
// ! tree
|
||||||
|
// four
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleGetContextDiffString() {
|
||||||
|
a := `one
|
||||||
|
two
|
||||||
|
three
|
||||||
|
four`
|
||||||
|
b := `zero
|
||||||
|
one
|
||||||
|
tree
|
||||||
|
four`
|
||||||
|
diff := ContextDiff{
|
||||||
|
A: SplitLines(a),
|
||||||
|
B: SplitLines(b),
|
||||||
|
FromFile: "Original",
|
||||||
|
ToFile: "Current",
|
||||||
|
Context: 3,
|
||||||
|
Eol: "\n",
|
||||||
|
}
|
||||||
|
result, _ := GetContextDiffString(diff)
|
||||||
|
fmt.Printf(strings.Replace(result, "\t", " ", -1))
|
||||||
|
// Output:
|
||||||
|
// *** Original
|
||||||
|
// --- Current
|
||||||
|
// ***************
|
||||||
|
// *** 1,4 ****
|
||||||
|
// one
|
||||||
|
// ! two
|
||||||
|
// ! three
|
||||||
|
// four
|
||||||
|
// --- 1,4 ----
|
||||||
|
// + zero
|
||||||
|
// one
|
||||||
|
// ! tree
|
||||||
|
// four
|
||||||
|
}
|
||||||
|
|
||||||
|
func rep(s string, count int) string {
|
||||||
|
return strings.Repeat(s, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithAsciiOneInsert(t *testing.T) {
|
||||||
|
sm := NewMatcher(splitChars(rep("b", 100)),
|
||||||
|
splitChars("a"+rep("b", 100)))
|
||||||
|
assertAlmostEqual(t, sm.Ratio(), 0.995, 3)
|
||||||
|
assertEqual(t, sm.GetOpCodes(),
|
||||||
|
[]OpCode{{'i', 0, 0, 0, 1}, {'e', 0, 100, 1, 101}})
|
||||||
|
assertEqual(t, len(sm.bPopular), 0)
|
||||||
|
|
||||||
|
sm = NewMatcher(splitChars(rep("b", 100)),
|
||||||
|
splitChars(rep("b", 50)+"a"+rep("b", 50)))
|
||||||
|
assertAlmostEqual(t, sm.Ratio(), 0.995, 3)
|
||||||
|
assertEqual(t, sm.GetOpCodes(),
|
||||||
|
[]OpCode{{'e', 0, 50, 0, 50}, {'i', 50, 50, 50, 51}, {'e', 50, 100, 51, 101}})
|
||||||
|
assertEqual(t, len(sm.bPopular), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithAsciiOnDelete(t *testing.T) {
|
||||||
|
sm := NewMatcher(splitChars(rep("a", 40)+"c"+rep("b", 40)),
|
||||||
|
splitChars(rep("a", 40)+rep("b", 40)))
|
||||||
|
assertAlmostEqual(t, sm.Ratio(), 0.994, 3)
|
||||||
|
assertEqual(t, sm.GetOpCodes(),
|
||||||
|
[]OpCode{{'e', 0, 40, 0, 40}, {'d', 40, 41, 40, 40}, {'e', 41, 81, 40, 80}})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWithAsciiBJunk(t *testing.T) {
|
||||||
|
isJunk := func(s string) bool {
|
||||||
|
return s == " "
|
||||||
|
}
|
||||||
|
sm := NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)),
|
||||||
|
splitChars(rep("a", 44)+rep("b", 40)), true, isJunk)
|
||||||
|
assertEqual(t, sm.bJunk, map[string]struct{}{})
|
||||||
|
|
||||||
|
sm = NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)),
|
||||||
|
splitChars(rep("a", 44)+rep("b", 40)+rep(" ", 20)), false, isJunk)
|
||||||
|
assertEqual(t, sm.bJunk, map[string]struct{}{" ": struct{}{}})
|
||||||
|
|
||||||
|
isJunk = func(s string) bool {
|
||||||
|
return s == " " || s == "b"
|
||||||
|
}
|
||||||
|
sm = NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)),
|
||||||
|
splitChars(rep("a", 44)+rep("b", 40)+rep(" ", 20)), false, isJunk)
|
||||||
|
assertEqual(t, sm.bJunk, map[string]struct{}{" ": struct{}{}, "b": struct{}{}})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSFBugsRatioForNullSeqn(t *testing.T) {
|
||||||
|
sm := NewMatcher(nil, nil)
|
||||||
|
assertEqual(t, sm.Ratio(), 1.0)
|
||||||
|
assertEqual(t, sm.QuickRatio(), 1.0)
|
||||||
|
assertEqual(t, sm.RealQuickRatio(), 1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSFBugsComparingEmptyLists(t *testing.T) {
|
||||||
|
groups := NewMatcher(nil, nil).GetGroupedOpCodes(-1)
|
||||||
|
assertEqual(t, len(groups), 0)
|
||||||
|
diff := UnifiedDiff{
|
||||||
|
FromFile: "Original",
|
||||||
|
ToFile: "Current",
|
||||||
|
Context: 3,
|
||||||
|
}
|
||||||
|
result, err := GetUnifiedDiffString(diff)
|
||||||
|
assertEqual(t, err, nil)
|
||||||
|
assertEqual(t, result, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOutputFormatRangeFormatUnified(t *testing.T) {
|
||||||
|
// Per the diff spec at http://www.unix.org/single_unix_specification/
|
||||||
|
//
|
||||||
|
// Each <range> field shall be of the form:
|
||||||
|
// %1d", <beginning line number> if the range contains exactly one line,
|
||||||
|
// and:
|
||||||
|
// "%1d,%1d", <beginning line number>, <number of lines> otherwise.
|
||||||
|
// If a range is empty, its beginning line number shall be the number of
|
||||||
|
// the line just before the range, or 0 if the empty range starts the file.
|
||||||
|
fm := formatRangeUnified
|
||||||
|
assertEqual(t, fm(3, 3), "3,0")
|
||||||
|
assertEqual(t, fm(3, 4), "4")
|
||||||
|
assertEqual(t, fm(3, 5), "4,2")
|
||||||
|
assertEqual(t, fm(3, 6), "4,3")
|
||||||
|
assertEqual(t, fm(0, 0), "0,0")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOutputFormatRangeFormatContext(t *testing.T) {
|
||||||
|
// Per the diff spec at http://www.unix.org/single_unix_specification/
|
||||||
|
//
|
||||||
|
// The range of lines in file1 shall be written in the following format
|
||||||
|
// if the range contains two or more lines:
|
||||||
|
// "*** %d,%d ****\n", <beginning line number>, <ending line number>
|
||||||
|
// and the following format otherwise:
|
||||||
|
// "*** %d ****\n", <ending line number>
|
||||||
|
// The ending line number of an empty range shall be the number of the preceding line,
|
||||||
|
// or 0 if the range is at the start of the file.
|
||||||
|
//
|
||||||
|
// Next, the range of lines in file2 shall be written in the following format
|
||||||
|
// if the range contains two or more lines:
|
||||||
|
// "--- %d,%d ----\n", <beginning line number>, <ending line number>
|
||||||
|
// and the following format otherwise:
|
||||||
|
// "--- %d ----\n", <ending line number>
|
||||||
|
fm := formatRangeContext
|
||||||
|
assertEqual(t, fm(3, 3), "3")
|
||||||
|
assertEqual(t, fm(3, 4), "4")
|
||||||
|
assertEqual(t, fm(3, 5), "4,5")
|
||||||
|
assertEqual(t, fm(3, 6), "4,6")
|
||||||
|
assertEqual(t, fm(0, 0), "0")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOutputFormatTabDelimiter(t *testing.T) {
|
||||||
|
diff := UnifiedDiff{
|
||||||
|
A: splitChars("one"),
|
||||||
|
B: splitChars("two"),
|
||||||
|
FromFile: "Original",
|
||||||
|
FromDate: "2005-01-26 23:30:50",
|
||||||
|
ToFile: "Current",
|
||||||
|
ToDate: "2010-04-12 10:20:52",
|
||||||
|
Eol: "\n",
|
||||||
|
}
|
||||||
|
ud, err := GetUnifiedDiffString(diff)
|
||||||
|
assertEqual(t, err, nil)
|
||||||
|
assertEqual(t, SplitLines(ud)[:2], []string{
|
||||||
|
"--- Original\t2005-01-26 23:30:50\n",
|
||||||
|
"+++ Current\t2010-04-12 10:20:52\n",
|
||||||
|
})
|
||||||
|
cd, err := GetContextDiffString(ContextDiff(diff))
|
||||||
|
assertEqual(t, err, nil)
|
||||||
|
assertEqual(t, SplitLines(cd)[:2], []string{
|
||||||
|
"*** Original\t2005-01-26 23:30:50\n",
|
||||||
|
"--- Current\t2010-04-12 10:20:52\n",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOutputFormatNoTrailingTabOnEmptyFiledate(t *testing.T) {
|
||||||
|
diff := UnifiedDiff{
|
||||||
|
A: splitChars("one"),
|
||||||
|
B: splitChars("two"),
|
||||||
|
FromFile: "Original",
|
||||||
|
ToFile: "Current",
|
||||||
|
Eol: "\n",
|
||||||
|
}
|
||||||
|
ud, err := GetUnifiedDiffString(diff)
|
||||||
|
assertEqual(t, err, nil)
|
||||||
|
assertEqual(t, SplitLines(ud)[:2], []string{"--- Original\n", "+++ Current\n"})
|
||||||
|
|
||||||
|
cd, err := GetContextDiffString(ContextDiff(diff))
|
||||||
|
assertEqual(t, err, nil)
|
||||||
|
assertEqual(t, SplitLines(cd)[:2], []string{"*** Original\n", "--- Current\n"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOmitFilenames(t *testing.T) {
|
||||||
|
diff := UnifiedDiff{
|
||||||
|
A: SplitLines("o\nn\ne\n"),
|
||||||
|
B: SplitLines("t\nw\no\n"),
|
||||||
|
Eol: "\n",
|
||||||
|
}
|
||||||
|
ud, err := GetUnifiedDiffString(diff)
|
||||||
|
assertEqual(t, err, nil)
|
||||||
|
assertEqual(t, SplitLines(ud), []string{
|
||||||
|
"@@ -0,0 +1,2 @@\n",
|
||||||
|
"+t\n",
|
||||||
|
"+w\n",
|
||||||
|
"@@ -2,2 +3,0 @@\n",
|
||||||
|
"-n\n",
|
||||||
|
"-e\n",
|
||||||
|
"\n",
|
||||||
|
})
|
||||||
|
|
||||||
|
cd, err := GetContextDiffString(ContextDiff(diff))
|
||||||
|
assertEqual(t, err, nil)
|
||||||
|
assertEqual(t, SplitLines(cd), []string{
|
||||||
|
"***************\n",
|
||||||
|
"*** 0 ****\n",
|
||||||
|
"--- 1,2 ----\n",
|
||||||
|
"+ t\n",
|
||||||
|
"+ w\n",
|
||||||
|
"***************\n",
|
||||||
|
"*** 2,3 ****\n",
|
||||||
|
"- n\n",
|
||||||
|
"- e\n",
|
||||||
|
"--- 3 ----\n",
|
||||||
|
"\n",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSplitLines(t *testing.T) {
|
||||||
|
allTests := []struct {
|
||||||
|
input string
|
||||||
|
want []string
|
||||||
|
}{
|
||||||
|
{"foo", []string{"foo\n"}},
|
||||||
|
{"foo\nbar", []string{"foo\n", "bar\n"}},
|
||||||
|
{"foo\nbar\n", []string{"foo\n", "bar\n", "\n"}},
|
||||||
|
}
|
||||||
|
for _, test := range allTests {
|
||||||
|
assertEqual(t, SplitLines(test.input), test.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkSplitLines(b *testing.B, count int) {
|
||||||
|
str := strings.Repeat("foo\n", count)
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
n := 0
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
n += len(SplitLines(str))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSplitLines100(b *testing.B) {
|
||||||
|
benchmarkSplitLines(b, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSplitLines10000(b *testing.B) {
|
||||||
|
benchmarkSplitLines(b, 10000)
|
||||||
|
}
|
||||||
17
Godeps/_workspace/src/github.com/samalba/dockerclient/README.md
generated
vendored
17
Godeps/_workspace/src/github.com/samalba/dockerclient/README.md
generated
vendored
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/samalba/dockerclient"
|
"github.com/samalba/dockerclient"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Callback used to listen to Docker's events
|
// Callback used to listen to Docker's events
|
||||||
|
|
@ -42,13 +43,27 @@ func main() {
|
||||||
log.Println(info)
|
log.Println(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build a docker image
|
||||||
|
// some.tar contains the build context (Dockerfile any any files it needs to add/copy)
|
||||||
|
dockerBuildContext, err := os.Open("some.tar")
|
||||||
|
defer dockerBuildContext.Close()
|
||||||
|
buildImageConfig := &dockerclient.BuildImage{
|
||||||
|
Context: dockerBuildContext,
|
||||||
|
RepoName: "your_image_name",
|
||||||
|
SuppressOutput: false,
|
||||||
|
}
|
||||||
|
reader, err := docker.BuildImage(buildImageConfig)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
// Create a container
|
// Create a container
|
||||||
containerConfig := &dockerclient.ContainerConfig{
|
containerConfig := &dockerclient.ContainerConfig{
|
||||||
Image: "ubuntu:14.04",
|
Image: "ubuntu:14.04",
|
||||||
Cmd: []string{"bash"},
|
Cmd: []string{"bash"},
|
||||||
AttachStdin: true,
|
AttachStdin: true,
|
||||||
Tty: true}
|
Tty: true}
|
||||||
containerId, err := docker.CreateContainer(containerConfig, "foobar")
|
containerId, err := docker.CreateContainer(containerConfig, "foobar", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
30
Godeps/_workspace/src/github.com/samalba/dockerclient/auth.go
generated
vendored
30
Godeps/_workspace/src/github.com/samalba/dockerclient/auth.go
generated
vendored
|
|
@ -8,14 +8,32 @@ import (
|
||||||
|
|
||||||
// AuthConfig hold parameters for authenticating with the docker registry
|
// AuthConfig hold parameters for authenticating with the docker registry
|
||||||
type AuthConfig struct {
|
type AuthConfig struct {
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
Password string `json:"password,omitempty"`
|
Password string `json:"password,omitempty"`
|
||||||
Email string `json:"email,omitempty"`
|
Email string `json:"email,omitempty"`
|
||||||
|
RegistryToken string `json:"registrytoken,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// encode the auth configuration struct into base64 for the X-Registry-Auth header
|
// encode the auth configuration struct into base64 for the X-Registry-Auth header
|
||||||
func (c *AuthConfig) encode() string {
|
func (c *AuthConfig) encode() (string, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
json.NewEncoder(&buf).Encode(c)
|
if err := json.NewEncoder(&buf).Encode(c); err != nil {
|
||||||
return base64.URLEncoding.EncodeToString(buf.Bytes())
|
return "", err
|
||||||
|
}
|
||||||
|
return base64.URLEncoding.EncodeToString(buf.Bytes()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ConfigFile holds parameters for authenticating during a BuildImage request
|
||||||
|
type ConfigFile struct {
|
||||||
|
Configs map[string]AuthConfig `json:"configs,omitempty"`
|
||||||
|
rootPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
// encode the configuration struct into base64 for the X-Registry-Config header
|
||||||
|
func (c *ConfigFile) encode() (string, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := json.NewEncoder(&buf).Encode(c); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return base64.URLEncoding.EncodeToString(buf.Bytes()), nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
15
Godeps/_workspace/src/github.com/samalba/dockerclient/auth_test.go
generated
vendored
15
Godeps/_workspace/src/github.com/samalba/dockerclient/auth_test.go
generated
vendored
|
|
@ -1,15 +0,0 @@
|
||||||
package dockerclient
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAuthEncode(t *testing.T) {
|
|
||||||
a := AuthConfig{Username: "foo", Password: "password", Email: "bar@baz.com"}
|
|
||||||
expected := "eyJ1c2VybmFtZSI6ImZvbyIsInBhc3N3b3JkIjoicGFzc3dvcmQiLCJlbWFpbCI6ImJhckBiYXouY29tIn0K"
|
|
||||||
got := a.encode()
|
|
||||||
|
|
||||||
if expected != got {
|
|
||||||
t.Errorf("testAuthEncode failed. Expected [%s] got [%s]", expected, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
496
Godeps/_workspace/src/github.com/samalba/dockerclient/dockerclient.go
generated
vendored
496
Godeps/_workspace/src/github.com/samalba/dockerclient/dockerclient.go
generated
vendored
|
|
@ -16,12 +16,23 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var _ Client = (*DockerClient)(nil)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// APIVersion is currently hardcoded to v1.15
|
||||||
|
// TODO: bump the API version or allow users to choose which API version to
|
||||||
|
// use the client with. The current value does not make sense for many
|
||||||
|
// methods, such as ContainerStats, StartMonitorStats, and StopAllMonitorStats
|
||||||
|
// (v1.17) and
|
||||||
|
// ListVolumes, {Remove,Create}Volume, ListNetworks,
|
||||||
|
// {Inspect,Create,Connect,Disconnect,Remove}Network (v1.21)
|
||||||
APIVersion = "v1.15"
|
APIVersion = "v1.15"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNotFound = errors.New("Not found")
|
ErrImageNotFound = errors.New("Image not found")
|
||||||
|
ErrNotFound = errors.New("Not found")
|
||||||
|
ErrConnectionRefused = errors.New("Cannot connect to the docker engine endpoint")
|
||||||
|
|
||||||
defaultTimeout = 30 * time.Second
|
defaultTimeout = 30 * time.Second
|
||||||
)
|
)
|
||||||
|
|
@ -45,10 +56,10 @@ func (e Error) Error() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDockerClient(daemonUrl string, tlsConfig *tls.Config) (*DockerClient, error) {
|
func NewDockerClient(daemonUrl string, tlsConfig *tls.Config) (*DockerClient, error) {
|
||||||
return NewDockerClientTimeout(daemonUrl, tlsConfig, time.Duration(defaultTimeout))
|
return NewDockerClientTimeout(daemonUrl, tlsConfig, time.Duration(defaultTimeout), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDockerClientTimeout(daemonUrl string, tlsConfig *tls.Config, timeout time.Duration) (*DockerClient, error) {
|
func NewDockerClientTimeout(daemonUrl string, tlsConfig *tls.Config, timeout time.Duration, setUserTimeout tcpFunc) (*DockerClient, error) {
|
||||||
u, err := url.Parse(daemonUrl)
|
u, err := url.Parse(daemonUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -60,7 +71,7 @@ func NewDockerClientTimeout(daemonUrl string, tlsConfig *tls.Config, timeout tim
|
||||||
u.Scheme = "https"
|
u.Scheme = "https"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
httpClient := newHTTPClient(u, tlsConfig, timeout)
|
httpClient := newHTTPClient(u, tlsConfig, timeout, setUserTimeout)
|
||||||
return &DockerClient{u, httpClient, tlsConfig, 0, nil}, nil
|
return &DockerClient{u, httpClient, tlsConfig, 0, nil}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,9 +110,24 @@ func (client *DockerClient) doStreamRequest(method string, path string, in io.Re
|
||||||
if !strings.Contains(err.Error(), "connection refused") && client.TLSConfig == nil {
|
if !strings.Contains(err.Error(), "connection refused") && client.TLSConfig == nil {
|
||||||
return nil, fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
|
return nil, fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
|
||||||
}
|
}
|
||||||
|
if strings.Contains(err.Error(), "connection refused") {
|
||||||
|
return nil, ErrConnectionRefused
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if resp.StatusCode == 404 {
|
if resp.StatusCode == 404 {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
data, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, ErrNotFound
|
||||||
|
}
|
||||||
|
if len(data) > 0 {
|
||||||
|
// check if is image not found error
|
||||||
|
if strings.Index(string(data), "No such image") != -1 {
|
||||||
|
return nil, ErrImageNotFound
|
||||||
|
}
|
||||||
|
return nil, errors.New(string(data))
|
||||||
|
}
|
||||||
return nil, ErrNotFound
|
return nil, ErrNotFound
|
||||||
}
|
}
|
||||||
if resp.StatusCode >= 400 {
|
if resp.StatusCode >= 400 {
|
||||||
|
|
@ -171,7 +197,7 @@ func (client *DockerClient) InspectContainer(id string) (*ContainerInfo, error)
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *DockerClient) CreateContainer(config *ContainerConfig, name string) (string, error) {
|
func (client *DockerClient) CreateContainer(config *ContainerConfig, name string, auth *AuthConfig) (string, error) {
|
||||||
data, err := json.Marshal(config)
|
data, err := json.Marshal(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
@ -182,14 +208,22 @@ func (client *DockerClient) CreateContainer(config *ContainerConfig, name string
|
||||||
v.Set("name", name)
|
v.Set("name", name)
|
||||||
uri = fmt.Sprintf("%s?%s", uri, v.Encode())
|
uri = fmt.Sprintf("%s?%s", uri, v.Encode())
|
||||||
}
|
}
|
||||||
data, err = client.doRequest("POST", uri, data, nil)
|
headers := map[string]string{}
|
||||||
|
if auth != nil {
|
||||||
|
encoded_auth, err := auth.encode()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
headers["X-Registry-Auth"] = encoded_auth
|
||||||
|
}
|
||||||
|
data, err = client.doRequest("POST", uri, data, headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
result := &RespContainersCreate{}
|
result := &RespContainersCreate{}
|
||||||
err = json.Unmarshal(data, result)
|
err = json.Unmarshal(data, result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", fmt.Errorf(string(data))
|
||||||
}
|
}
|
||||||
return result.Id, nil
|
return result.Id, nil
|
||||||
}
|
}
|
||||||
|
|
@ -231,25 +265,64 @@ func (client *DockerClient) ContainerChanges(id string) ([]*ContainerChanges, er
|
||||||
return changes, nil
|
return changes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) ContainerStats(id string, stopChan <-chan struct{}) (<-chan StatsOrError, error) {
|
||||||
|
uri := fmt.Sprintf("/%s/containers/%s/stats", APIVersion, id)
|
||||||
|
resp, err := client.HTTPClient.Get(client.URL.String() + uri)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
decode := func(decoder *json.Decoder) decodingResult {
|
||||||
|
var containerStats Stats
|
||||||
|
if err := decoder.Decode(&containerStats); err != nil {
|
||||||
|
return decodingResult{err: err}
|
||||||
|
} else {
|
||||||
|
return decodingResult{result: containerStats}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decodingResultChan := client.readJSONStream(resp.Body, decode, stopChan)
|
||||||
|
statsOrErrorChan := make(chan StatsOrError)
|
||||||
|
go func() {
|
||||||
|
for decodingResult := range decodingResultChan {
|
||||||
|
stats, _ := decodingResult.result.(Stats)
|
||||||
|
statsOrErrorChan <- StatsOrError{
|
||||||
|
Stats: stats,
|
||||||
|
Error: decodingResult.err,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(statsOrErrorChan)
|
||||||
|
}()
|
||||||
|
return statsOrErrorChan, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (client *DockerClient) readJSONStream(stream io.ReadCloser, decode func(*json.Decoder) decodingResult, stopChan <-chan struct{}) <-chan decodingResult {
|
func (client *DockerClient) readJSONStream(stream io.ReadCloser, decode func(*json.Decoder) decodingResult, stopChan <-chan struct{}) <-chan decodingResult {
|
||||||
resultChan := make(chan decodingResult)
|
resultChan := make(chan decodingResult)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
decoder := json.NewDecoder(stream)
|
decodeChan := make(chan decodingResult)
|
||||||
stopped := make(chan struct{})
|
|
||||||
go func() {
|
go func() {
|
||||||
<-stopChan
|
decoder := json.NewDecoder(stream)
|
||||||
stream.Close()
|
for {
|
||||||
stopped <- struct{}{}
|
decodeResult := decode(decoder)
|
||||||
|
decodeChan <- decodeResult
|
||||||
|
if decodeResult.err != nil {
|
||||||
|
close(decodeChan)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
defer close(resultChan)
|
defer close(resultChan)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
decodeResult := decode(decoder)
|
|
||||||
select {
|
select {
|
||||||
case <-stopped:
|
case <-stopChan:
|
||||||
|
stream.Close()
|
||||||
|
for range decodeChan {
|
||||||
|
}
|
||||||
return
|
return
|
||||||
default:
|
case decodeResult := <-decodeChan:
|
||||||
resultChan <- decodeResult
|
resultChan <- decodeResult
|
||||||
if decodeResult.err != nil {
|
if decodeResult.err != nil {
|
||||||
stream.Close()
|
stream.Close()
|
||||||
|
|
@ -257,11 +330,85 @@ func (client *DockerClient) readJSONStream(stream io.ReadCloser, decode func(*js
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return resultChan
|
return resultChan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) ExecCreate(config *ExecConfig) (string, error) {
|
||||||
|
data, err := json.Marshal(config)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
uri := fmt.Sprintf("/%s/containers/%s/exec", APIVersion, config.Container)
|
||||||
|
resp, err := client.doRequest("POST", uri, data, nil)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var createExecResp struct {
|
||||||
|
Id string
|
||||||
|
}
|
||||||
|
if err = json.Unmarshal(resp, &createExecResp); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return createExecResp.Id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) ExecStart(id string, config *ExecConfig) error {
|
||||||
|
data, err := json.Marshal(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
uri := fmt.Sprintf("/%s/exec/%s/start", APIVersion, id)
|
||||||
|
if _, err := client.doRequest("POST", uri, data, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) ExecResize(id string, width, height int) error {
|
||||||
|
v := url.Values{}
|
||||||
|
|
||||||
|
w := strconv.Itoa(width)
|
||||||
|
h := strconv.Itoa(height)
|
||||||
|
|
||||||
|
v.Set("w", w)
|
||||||
|
v.Set("h", h)
|
||||||
|
|
||||||
|
uri := fmt.Sprintf("/%s/exec/%s/resize?%s", APIVersion, id, v.Encode())
|
||||||
|
if _, err := client.doRequest("POST", client.URL.String()+uri, nil, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) AttachContainer(id string, options *AttachOptions) (io.ReadCloser, error) {
|
||||||
|
v := url.Values{}
|
||||||
|
if options != nil {
|
||||||
|
if options.Logs {
|
||||||
|
v.Set("logs", "1")
|
||||||
|
}
|
||||||
|
if options.Stream {
|
||||||
|
v.Set("stream", "1")
|
||||||
|
}
|
||||||
|
if options.Stdin {
|
||||||
|
v.Set("stdin", "1")
|
||||||
|
}
|
||||||
|
if options.Stdout {
|
||||||
|
v.Set("stdout", "1")
|
||||||
|
}
|
||||||
|
if options.Stderr {
|
||||||
|
v.Set("stderr", "1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uri := fmt.Sprintf("/%s/containers/%s/attach?%s", APIVersion, id, v.Encode())
|
||||||
|
return client.doStreamRequest("POST", uri, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
func (client *DockerClient) StartContainer(id string, config *HostConfig) error {
|
func (client *DockerClient) StartContainer(id string, config *HostConfig) error {
|
||||||
data, err := json.Marshal(config)
|
data, err := json.Marshal(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -302,6 +449,26 @@ func (client *DockerClient) KillContainer(id, signal string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) Wait(id string) <-chan WaitResult {
|
||||||
|
ch := make(chan WaitResult)
|
||||||
|
uri := fmt.Sprintf("/%s/containers/%s/wait", APIVersion, id)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
data, err := client.doRequest("POST", uri, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
ch <- WaitResult{ExitCode: -1, Error: err}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var result struct {
|
||||||
|
StatusCode int `json:"StatusCode"`
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(data, &result)
|
||||||
|
ch <- WaitResult{ExitCode: result.StatusCode, Error: err}
|
||||||
|
}()
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
func (client *DockerClient) MonitorEvents(options *MonitorEventsOptions, stopChan <-chan struct{}) (<-chan EventOrError, error) {
|
func (client *DockerClient) MonitorEvents(options *MonitorEventsOptions, stopChan <-chan struct{}) (<-chan EventOrError, error) {
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
if options != nil {
|
if options != nil {
|
||||||
|
|
@ -366,13 +533,17 @@ func (client *DockerClient) StartMonitorEvents(cb Callback, ec chan error, args
|
||||||
go func() {
|
go func() {
|
||||||
eventErrChan, err := client.MonitorEvents(nil, client.eventStopChan)
|
eventErrChan, err := client.MonitorEvents(nil, client.eventStopChan)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec <- err
|
if ec != nil {
|
||||||
|
ec <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for e := range eventErrChan {
|
for e := range eventErrChan {
|
||||||
if e.Error != nil {
|
if e.Error != nil {
|
||||||
ec <- err
|
if ec != nil {
|
||||||
|
ec <- e.Error
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cb(&e.Event, ec, args...)
|
cb(&e.Event, ec, args...)
|
||||||
|
|
@ -381,6 +552,9 @@ func (client *DockerClient) StartMonitorEvents(cb Callback, ec chan error, args
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *DockerClient) StopAllMonitorEvents() {
|
func (client *DockerClient) StopAllMonitorEvents() {
|
||||||
|
if client.eventStopChan == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
close(client.eventStopChan)
|
close(client.eventStopChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -441,13 +615,48 @@ func (client *DockerClient) Version() (*Version, error) {
|
||||||
return version, nil
|
return version, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) PushImage(name string, tag string, auth *AuthConfig) error {
|
||||||
|
v := url.Values{}
|
||||||
|
if tag != "" {
|
||||||
|
v.Set("tag", tag)
|
||||||
|
}
|
||||||
|
uri := fmt.Sprintf("/%s/images/%s/push?%s", APIVersion, url.QueryEscape(name), v.Encode())
|
||||||
|
req, err := http.NewRequest("POST", client.URL.String()+uri, nil)
|
||||||
|
if auth != nil {
|
||||||
|
if encodedAuth, err := auth.encode(); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
req.Header.Add("X-Registry-Auth", encodedAuth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp, err := client.HTTPClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
var finalObj map[string]interface{}
|
||||||
|
for decoder := json.NewDecoder(resp.Body); err == nil; err = decoder.Decode(&finalObj) {
|
||||||
|
}
|
||||||
|
if err != io.EOF {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err, ok := finalObj["error"]; ok {
|
||||||
|
return fmt.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (client *DockerClient) PullImage(name string, auth *AuthConfig) error {
|
func (client *DockerClient) PullImage(name string, auth *AuthConfig) error {
|
||||||
v := url.Values{}
|
v := url.Values{}
|
||||||
v.Set("fromImage", name)
|
v.Set("fromImage", name)
|
||||||
uri := fmt.Sprintf("/%s/images/create?%s", APIVersion, v.Encode())
|
uri := fmt.Sprintf("/%s/images/create?%s", APIVersion, v.Encode())
|
||||||
req, err := http.NewRequest("POST", client.URL.String()+uri, nil)
|
req, err := http.NewRequest("POST", client.URL.String()+uri, nil)
|
||||||
if auth != nil {
|
if auth != nil {
|
||||||
req.Header.Add("X-Registry-Auth", auth.encode())
|
encoded_auth, err := auth.encode()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Add("X-Registry-Auth", encoded_auth)
|
||||||
}
|
}
|
||||||
resp, err := client.HTTPClient.Do(req)
|
resp, err := client.HTTPClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -493,17 +702,9 @@ func (client *DockerClient) InspectImage(id string) (*ImageInfo, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *DockerClient) LoadImage(reader io.Reader) error {
|
func (client *DockerClient) LoadImage(reader io.Reader) error {
|
||||||
data, err := ioutil.ReadAll(reader)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
uri := fmt.Sprintf("/%s/images/load", APIVersion)
|
uri := fmt.Sprintf("/%s/images/load", APIVersion)
|
||||||
_, err = client.doRequest("POST", uri, data, nil)
|
_, err := client.doStreamRequest("POST", uri, reader, nil)
|
||||||
if err != nil {
|
return err
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *DockerClient) RemoveContainer(id string, force, volumes bool) error {
|
func (client *DockerClient) RemoveContainer(id string, force, volumes bool) error {
|
||||||
|
|
@ -521,8 +722,12 @@ func (client *DockerClient) RemoveContainer(id string, force, volumes bool) erro
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *DockerClient) ListImages() ([]*Image, error) {
|
func (client *DockerClient) ListImages(all bool) ([]*Image, error) {
|
||||||
uri := fmt.Sprintf("/%s/images/json", APIVersion)
|
argAll := 0
|
||||||
|
if all {
|
||||||
|
argAll = 1
|
||||||
|
}
|
||||||
|
uri := fmt.Sprintf("/%s/images/json?all=%d", APIVersion, argAll)
|
||||||
data, err := client.doRequest("GET", uri, nil, nil)
|
data, err := client.doRequest("GET", uri, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -534,8 +739,14 @@ func (client *DockerClient) ListImages() ([]*Image, error) {
|
||||||
return images, nil
|
return images, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *DockerClient) RemoveImage(name string) ([]*ImageDelete, error) {
|
func (client *DockerClient) RemoveImage(name string, force bool) ([]*ImageDelete, error) {
|
||||||
uri := fmt.Sprintf("/%s/images/%s", APIVersion, name)
|
argForce := 0
|
||||||
|
if force {
|
||||||
|
argForce = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
args := fmt.Sprintf("force=%d", argForce)
|
||||||
|
uri := fmt.Sprintf("/%s/images/%s?%s", APIVersion, name, args)
|
||||||
data, err := client.doRequest("DELETE", uri, nil, nil)
|
data, err := client.doRequest("DELETE", uri, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -547,6 +758,31 @@ func (client *DockerClient) RemoveImage(name string) ([]*ImageDelete, error) {
|
||||||
return imageDelete, nil
|
return imageDelete, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) SearchImages(query, registry string, auth *AuthConfig) ([]ImageSearch, error) {
|
||||||
|
term := query
|
||||||
|
if registry != "" {
|
||||||
|
term = registry + "/" + term
|
||||||
|
}
|
||||||
|
uri := fmt.Sprintf("/%s/images/search?term=%s", APIVersion, term)
|
||||||
|
headers := map[string]string{}
|
||||||
|
if auth != nil {
|
||||||
|
if encodedAuth, err := auth.encode(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
headers["X-Registry-Auth"] = encodedAuth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data, err := client.doRequest("GET", uri, nil, headers)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var imageSearches []ImageSearch
|
||||||
|
if err := json.Unmarshal(data, &imageSearches); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return imageSearches, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (client *DockerClient) PauseContainer(id string) error {
|
func (client *DockerClient) PauseContainer(id string) error {
|
||||||
uri := fmt.Sprintf("/%s/containers/%s/pause", APIVersion, id)
|
uri := fmt.Sprintf("/%s/containers/%s/pause", APIVersion, id)
|
||||||
_, err := client.doRequest("POST", uri, nil, nil)
|
_, err := client.doRequest("POST", uri, nil, nil)
|
||||||
|
|
@ -564,30 +800,6 @@ func (client *DockerClient) UnpauseContainer(id string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *DockerClient) Exec(config *ExecConfig) (string, error) {
|
|
||||||
data, err := json.Marshal(config)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
uri := fmt.Sprintf("/containers/%s/exec", config.Container)
|
|
||||||
resp, err := client.doRequest("POST", uri, data, nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
var createExecResp struct {
|
|
||||||
Id string
|
|
||||||
}
|
|
||||||
if err = json.Unmarshal(resp, &createExecResp); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
uri = fmt.Sprintf("/exec/%s/start", createExecResp.Id)
|
|
||||||
resp, err = client.doRequest("POST", uri, data, nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return createExecResp.Id, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *DockerClient) RenameContainer(oldName string, newName string) error {
|
func (client *DockerClient) RenameContainer(oldName string, newName string) error {
|
||||||
uri := fmt.Sprintf("/containers/%s/rename?name=%s", oldName, newName)
|
uri := fmt.Sprintf("/containers/%s/rename?name=%s", oldName, newName)
|
||||||
_, err := client.doRequest("POST", uri, nil, nil)
|
_, err := client.doRequest("POST", uri, nil, nil)
|
||||||
|
|
@ -615,3 +827,175 @@ func (client *DockerClient) ImportImage(source string, repository string, tag st
|
||||||
}
|
}
|
||||||
return client.doStreamRequest("POST", "/images/create?"+v.Encode(), in, nil)
|
return client.doStreamRequest("POST", "/images/create?"+v.Encode(), in, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) BuildImage(image *BuildImage) (io.ReadCloser, error) {
|
||||||
|
v := url.Values{}
|
||||||
|
|
||||||
|
if image.DockerfileName != "" {
|
||||||
|
v.Set("dockerfile", image.DockerfileName)
|
||||||
|
}
|
||||||
|
if image.RepoName != "" {
|
||||||
|
v.Set("t", image.RepoName)
|
||||||
|
}
|
||||||
|
if image.RemoteURL != "" {
|
||||||
|
v.Set("remote", image.RemoteURL)
|
||||||
|
}
|
||||||
|
if image.NoCache {
|
||||||
|
v.Set("nocache", "1")
|
||||||
|
}
|
||||||
|
if image.Pull {
|
||||||
|
v.Set("pull", "1")
|
||||||
|
}
|
||||||
|
if image.Remove {
|
||||||
|
v.Set("rm", "1")
|
||||||
|
} else {
|
||||||
|
v.Set("rm", "0")
|
||||||
|
}
|
||||||
|
if image.ForceRemove {
|
||||||
|
v.Set("forcerm", "1")
|
||||||
|
}
|
||||||
|
if image.SuppressOutput {
|
||||||
|
v.Set("q", "1")
|
||||||
|
}
|
||||||
|
|
||||||
|
v.Set("memory", strconv.FormatInt(image.Memory, 10))
|
||||||
|
v.Set("memswap", strconv.FormatInt(image.MemorySwap, 10))
|
||||||
|
v.Set("cpushares", strconv.FormatInt(image.CpuShares, 10))
|
||||||
|
v.Set("cpuperiod", strconv.FormatInt(image.CpuPeriod, 10))
|
||||||
|
v.Set("cpuquota", strconv.FormatInt(image.CpuQuota, 10))
|
||||||
|
v.Set("cpusetcpus", image.CpuSetCpus)
|
||||||
|
v.Set("cpusetmems", image.CpuSetMems)
|
||||||
|
v.Set("cgroupparent", image.CgroupParent)
|
||||||
|
if image.BuildArgs != nil {
|
||||||
|
buildArgsJSON, err := json.Marshal(image.BuildArgs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
v.Set("buildargs", string(buildArgsJSON))
|
||||||
|
}
|
||||||
|
|
||||||
|
headers := make(map[string]string)
|
||||||
|
if image.Config != nil {
|
||||||
|
encoded_config, err := image.Config.encode()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
headers["X-Registry-Config"] = encoded_config
|
||||||
|
}
|
||||||
|
if image.Context != nil {
|
||||||
|
headers["Content-Type"] = "application/tar"
|
||||||
|
}
|
||||||
|
|
||||||
|
uri := fmt.Sprintf("/%s/build?%s", APIVersion, v.Encode())
|
||||||
|
return client.doStreamRequest("POST", uri, image.Context, headers)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) ListVolumes() ([]*Volume, error) {
|
||||||
|
uri := fmt.Sprintf("/%s/volumes", APIVersion)
|
||||||
|
data, err := client.doRequest("GET", uri, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var volumesList VolumesListResponse
|
||||||
|
if err := json.Unmarshal(data, &volumesList); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return volumesList.Volumes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) RemoveVolume(name string) error {
|
||||||
|
uri := fmt.Sprintf("/%s/volumes/%s", APIVersion, name)
|
||||||
|
_, err := client.doRequest("DELETE", uri, nil, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) CreateVolume(request *VolumeCreateRequest) (*Volume, error) {
|
||||||
|
data, err := json.Marshal(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
uri := fmt.Sprintf("/%s/volumes/create", APIVersion)
|
||||||
|
data, err = client.doRequest("POST", uri, data, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
volume := &Volume{}
|
||||||
|
err = json.Unmarshal(data, volume)
|
||||||
|
return volume, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) ListNetworks(filters string) ([]*NetworkResource, error) {
|
||||||
|
uri := fmt.Sprintf("/%s/networks", APIVersion)
|
||||||
|
|
||||||
|
if filters != "" {
|
||||||
|
uri += "&filters=" + filters
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := client.doRequest("GET", uri, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret := []*NetworkResource{}
|
||||||
|
err = json.Unmarshal(data, &ret)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) InspectNetwork(id string) (*NetworkResource, error) {
|
||||||
|
uri := fmt.Sprintf("/%s/networks/%s", APIVersion, id)
|
||||||
|
|
||||||
|
data, err := client.doRequest("GET", uri, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret := &NetworkResource{}
|
||||||
|
err = json.Unmarshal(data, ret)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) CreateNetwork(config *NetworkCreate) (*NetworkCreateResponse, error) {
|
||||||
|
data, err := json.Marshal(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
uri := fmt.Sprintf("/%s/networks/create", APIVersion)
|
||||||
|
data, err = client.doRequest("POST", uri, data, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ret := &NetworkCreateResponse{}
|
||||||
|
err = json.Unmarshal(data, ret)
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) ConnectNetwork(id, container string) error {
|
||||||
|
data, err := json.Marshal(NetworkConnect{Container: container})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
uri := fmt.Sprintf("/%s/networks/%s/connect", APIVersion, id)
|
||||||
|
_, err = client.doRequest("POST", uri, data, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) DisconnectNetwork(id, container string, force bool) error {
|
||||||
|
data, err := json.Marshal(NetworkDisconnect{Container: container, Force: force})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
uri := fmt.Sprintf("/%s/networks/%s/disconnect", APIVersion, id)
|
||||||
|
_, err = client.doRequest("POST", uri, data, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *DockerClient) RemoveNetwork(id string) error {
|
||||||
|
uri := fmt.Sprintf("/%s/networks/%s", APIVersion, id)
|
||||||
|
_, err := client.doRequest("DELETE", uri, nil, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
||||||
219
Godeps/_workspace/src/github.com/samalba/dockerclient/dockerclient_test.go
generated
vendored
219
Godeps/_workspace/src/github.com/samalba/dockerclient/dockerclient_test.go
generated
vendored
|
|
@ -1,219 +0,0 @@
|
||||||
package dockerclient
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/stdcopy"
|
|
||||||
)
|
|
||||||
|
|
||||||
func assertEqual(t *testing.T, a interface{}, b interface{}, message string) {
|
|
||||||
if a == b {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(message) == 0 {
|
|
||||||
message = fmt.Sprintf("%v != %v", a, b)
|
|
||||||
}
|
|
||||||
t.Fatal(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
func testDockerClient(t *testing.T) *DockerClient {
|
|
||||||
client, err := NewDockerClient(testHTTPServer.URL, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Cannot init the docker client")
|
|
||||||
}
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInfo(t *testing.T) {
|
|
||||||
client := testDockerClient(t)
|
|
||||||
info, err := client.Info()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Cannot get server info")
|
|
||||||
}
|
|
||||||
assertEqual(t, info.Images, int64(1), "")
|
|
||||||
assertEqual(t, info.Containers, int64(2), "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestKillContainer(t *testing.T) {
|
|
||||||
client := testDockerClient(t)
|
|
||||||
if err := client.KillContainer("23132acf2ac", "5"); err != nil {
|
|
||||||
t.Fatal("cannot kill container: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPullImage(t *testing.T) {
|
|
||||||
client := testDockerClient(t)
|
|
||||||
err := client.PullImage("busybox", nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("unable to pull busybox")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = client.PullImage("haproxy", nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("unable to pull haproxy")
|
|
||||||
}
|
|
||||||
|
|
||||||
err = client.PullImage("wrongimg", nil)
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("should return error when it fails to pull wrongimg")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListContainers(t *testing.T) {
|
|
||||||
client := testDockerClient(t)
|
|
||||||
containers, err := client.ListContainers(true, false, "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("cannot get containers: %s", err)
|
|
||||||
}
|
|
||||||
assertEqual(t, len(containers), 1, "")
|
|
||||||
cnt := containers[0]
|
|
||||||
assertEqual(t, cnt.SizeRw, int64(0), "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContainerChanges(t *testing.T) {
|
|
||||||
client := testDockerClient(t)
|
|
||||||
changes, err := client.ContainerChanges("foobar")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("cannot get container changes: %s", err)
|
|
||||||
}
|
|
||||||
assertEqual(t, len(changes), 3, "unexpected number of changes")
|
|
||||||
c := changes[0]
|
|
||||||
assertEqual(t, c.Path, "/dev", "unexpected")
|
|
||||||
assertEqual(t, c.Kind, 0, "unexpected")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestListContainersWithSize(t *testing.T) {
|
|
||||||
client := testDockerClient(t)
|
|
||||||
containers, err := client.ListContainers(true, true, "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("cannot get containers: %s", err)
|
|
||||||
}
|
|
||||||
assertEqual(t, len(containers), 1, "")
|
|
||||||
cnt := containers[0]
|
|
||||||
assertEqual(t, cnt.SizeRw, int64(123), "")
|
|
||||||
}
|
|
||||||
func TestListContainersWithFilters(t *testing.T) {
|
|
||||||
client := testDockerClient(t)
|
|
||||||
containers, err := client.ListContainers(true, true, "{'id':['332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688ce']}")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("cannot get containers: %s", err)
|
|
||||||
}
|
|
||||||
assertEqual(t, len(containers), 1, "")
|
|
||||||
|
|
||||||
containers, err = client.ListContainers(true, true, "{'id':['332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688cf']}")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("cannot get containers: %s", err)
|
|
||||||
}
|
|
||||||
assertEqual(t, len(containers), 0, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestContainerLogs(t *testing.T) {
|
|
||||||
client := testDockerClient(t)
|
|
||||||
containerId := "foobar"
|
|
||||||
logOptions := &LogOptions{
|
|
||||||
Follow: true,
|
|
||||||
Stdout: true,
|
|
||||||
Stderr: true,
|
|
||||||
Timestamps: true,
|
|
||||||
Tail: 10,
|
|
||||||
}
|
|
||||||
logsReader, err := client.ContainerLogs(containerId, logOptions)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("cannot read logs from server")
|
|
||||||
}
|
|
||||||
|
|
||||||
stdoutBuffer := new(bytes.Buffer)
|
|
||||||
stderrBuffer := new(bytes.Buffer)
|
|
||||||
if _, err = stdcopy.StdCopy(stdoutBuffer, stderrBuffer, logsReader); err != nil {
|
|
||||||
t.Fatal("cannot read logs from logs reader")
|
|
||||||
}
|
|
||||||
stdoutLogs := strings.TrimSpace(stdoutBuffer.String())
|
|
||||||
stderrLogs := strings.TrimSpace(stderrBuffer.String())
|
|
||||||
stdoutLogLines := strings.Split(stdoutLogs, "\n")
|
|
||||||
stderrLogLines := strings.Split(stderrLogs, "\n")
|
|
||||||
if len(stdoutLogLines) != 5 {
|
|
||||||
t.Fatalf("wrong number of stdout logs: len=%d", len(stdoutLogLines))
|
|
||||||
}
|
|
||||||
if len(stderrLogLines) != 5 {
|
|
||||||
t.Fatalf("wrong number of stderr logs: len=%d", len(stdoutLogLines))
|
|
||||||
}
|
|
||||||
for i, line := range stdoutLogLines {
|
|
||||||
expectedSuffix := fmt.Sprintf("Z line %d", 41+2*i)
|
|
||||||
if !strings.HasSuffix(line, expectedSuffix) {
|
|
||||||
t.Fatalf("expected stdout log line \"%s\" to end with \"%s\"", line, expectedSuffix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i, line := range stderrLogLines {
|
|
||||||
expectedSuffix := fmt.Sprintf("Z line %d", 40+2*i)
|
|
||||||
if !strings.HasSuffix(line, expectedSuffix) {
|
|
||||||
t.Fatalf("expected stderr log line \"%s\" to end with \"%s\"", line, expectedSuffix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMonitorEvents(t *testing.T) {
|
|
||||||
client := testDockerClient(t)
|
|
||||||
decoder := json.NewDecoder(bytes.NewBufferString(eventsResp))
|
|
||||||
var expectedEvents []Event
|
|
||||||
for {
|
|
||||||
var event Event
|
|
||||||
if err := decoder.Decode(&event); err != nil {
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
t.Fatalf("cannot parse expected resp: %s", err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
expectedEvents = append(expectedEvents, event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// test passing stop chan
|
|
||||||
stopChan := make(chan struct{})
|
|
||||||
eventInfoChan, err := client.MonitorEvents(nil, stopChan)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("cannot get events from server: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
eventInfo := <-eventInfoChan
|
|
||||||
if eventInfo.Error != nil || eventInfo.Event != expectedEvents[0] {
|
|
||||||
t.Fatalf("got:\n%#v\nexpected:\n%#v", eventInfo, expectedEvents[0])
|
|
||||||
}
|
|
||||||
close(stopChan)
|
|
||||||
for i := 0; i < 3; i++ {
|
|
||||||
_, ok := <-eventInfoChan
|
|
||||||
if i == 2 && ok {
|
|
||||||
t.Fatalf("read more than 2 events successfully after closing stopChan")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// test when you don't pass stop chan
|
|
||||||
eventInfoChan, err = client.MonitorEvents(nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("cannot get events from server: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, expectedEvent := range expectedEvents {
|
|
||||||
t.Logf("on iter %d\n", i)
|
|
||||||
eventInfo := <-eventInfoChan
|
|
||||||
if eventInfo.Error != nil || eventInfo.Event != expectedEvent {
|
|
||||||
t.Fatalf("index %d, got:\n%#v\nexpected:\n%#v", i, eventInfo, expectedEvent)
|
|
||||||
}
|
|
||||||
t.Logf("done with iter %d\n", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDockerClientInterface(t *testing.T) {
|
|
||||||
iface := reflect.TypeOf((*Client)(nil)).Elem()
|
|
||||||
test := testDockerClient(t)
|
|
||||||
|
|
||||||
if !reflect.TypeOf(test).Implements(iface) {
|
|
||||||
t.Fatalf("DockerClient does not implement the Client interface")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
235
Godeps/_workspace/src/github.com/samalba/dockerclient/engine_mock_test.go
generated
vendored
235
Godeps/_workspace/src/github.com/samalba/dockerclient/engine_mock_test.go
generated
vendored
|
|
@ -1,235 +0,0 @@
|
||||||
package dockerclient
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
|
||||||
"github.com/docker/docker/pkg/jsonlog"
|
|
||||||
"github.com/docker/docker/pkg/stdcopy"
|
|
||||||
"github.com/docker/docker/pkg/timeutils"
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
testHTTPServer *httptest.Server
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
r := mux.NewRouter()
|
|
||||||
baseURL := "/" + APIVersion
|
|
||||||
r.HandleFunc(baseURL+"/info", handlerGetInfo).Methods("GET")
|
|
||||||
r.HandleFunc(baseURL+"/containers/json", handlerGetContainers).Methods("GET")
|
|
||||||
r.HandleFunc(baseURL+"/containers/{id}/logs", handleContainerLogs).Methods("GET")
|
|
||||||
r.HandleFunc(baseURL+"/containers/{id}/changes", handleContainerChanges).Methods("GET")
|
|
||||||
r.HandleFunc(baseURL+"/containers/{id}/kill", handleContainerKill).Methods("POST")
|
|
||||||
r.HandleFunc(baseURL+"/images/create", handleImagePull).Methods("POST")
|
|
||||||
r.HandleFunc(baseURL+"/events", handleEvents).Methods("GET")
|
|
||||||
testHTTPServer = httptest.NewServer(handlerAccessLog(r))
|
|
||||||
}
|
|
||||||
|
|
||||||
func handlerAccessLog(handler http.Handler) http.Handler {
|
|
||||||
logHandler := func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
log.Printf("%s \"%s %s\"", r.RemoteAddr, r.Method, r.URL)
|
|
||||||
handler.ServeHTTP(w, r)
|
|
||||||
}
|
|
||||||
return http.HandlerFunc(logHandler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleContainerKill(w http.ResponseWriter, r *http.Request) {
|
|
||||||
fmt.Fprintf(w, "{%q:%q", "Id", "421373210afd132")
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleImagePull(w http.ResponseWriter, r *http.Request) {
|
|
||||||
imageName := r.URL.Query()["fromImage"][0]
|
|
||||||
responses := []map[string]interface{}{{
|
|
||||||
"status": fmt.Sprintf("Pulling repository mydockerregistry/%s", imageName),
|
|
||||||
}}
|
|
||||||
switch imageName {
|
|
||||||
case "busybox":
|
|
||||||
responses = append(responses, map[string]interface{}{
|
|
||||||
"status": "Status: Image is up to date for mydockerregistry/busybox",
|
|
||||||
})
|
|
||||||
case "haproxy":
|
|
||||||
fmt.Fprintf(w, haproxyPullOutput)
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
errorMsg := fmt.Sprintf("Error: image %s not found", imageName)
|
|
||||||
responses = append(responses, map[string]interface{}{
|
|
||||||
"errorDetail": map[string]interface{}{
|
|
||||||
"message": errorMsg,
|
|
||||||
},
|
|
||||||
"error": errorMsg,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
for _, response := range responses {
|
|
||||||
json.NewEncoder(w).Encode(response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleContainerLogs(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var outStream, errStream io.Writer
|
|
||||||
outStream = ioutils.NewWriteFlusher(w)
|
|
||||||
|
|
||||||
// not sure how to test follow
|
|
||||||
if err := r.ParseForm(); err != nil {
|
|
||||||
http.Error(w, err.Error(), 500)
|
|
||||||
}
|
|
||||||
stdout, stderr := getBoolValue(r.Form.Get("stdout")), getBoolValue(r.Form.Get("stderr"))
|
|
||||||
if stderr {
|
|
||||||
errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
|
|
||||||
}
|
|
||||||
if stdout {
|
|
||||||
outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
|
|
||||||
}
|
|
||||||
var i int
|
|
||||||
if tail, err := strconv.Atoi(r.Form.Get("tail")); err == nil && tail > 0 {
|
|
||||||
i = 50 - tail
|
|
||||||
if i < 0 {
|
|
||||||
i = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for ; i < 50; i++ {
|
|
||||||
line := fmt.Sprintf("line %d", i)
|
|
||||||
if getBoolValue(r.Form.Get("timestamps")) {
|
|
||||||
l := &jsonlog.JSONLog{Log: line, Created: time.Now()}
|
|
||||||
line = fmt.Sprintf("%s %s", l.Created.Format(timeutils.RFC3339NanoFixed), line)
|
|
||||||
}
|
|
||||||
if i%2 == 0 && stderr {
|
|
||||||
fmt.Fprintln(errStream, line)
|
|
||||||
} else if i%2 == 1 && stdout {
|
|
||||||
fmt.Fprintln(outStream, line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleContainerChanges(w http.ResponseWriter, r *http.Request) {
|
|
||||||
writeHeaders(w, 200, "changes")
|
|
||||||
body := `[
|
|
||||||
{
|
|
||||||
"Path": "/dev",
|
|
||||||
"Kind": 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Path": "/dev/kmsg",
|
|
||||||
"Kind": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Path": "/test",
|
|
||||||
"Kind": 1
|
|
||||||
}
|
|
||||||
]`
|
|
||||||
w.Write([]byte(body))
|
|
||||||
}
|
|
||||||
|
|
||||||
func getBoolValue(boolString string) bool {
|
|
||||||
switch boolString {
|
|
||||||
case "1":
|
|
||||||
return true
|
|
||||||
case "True":
|
|
||||||
return true
|
|
||||||
case "true":
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeHeaders(w http.ResponseWriter, code int, jobName string) {
|
|
||||||
h := w.Header()
|
|
||||||
h.Add("Content-Type", "application/json")
|
|
||||||
if jobName != "" {
|
|
||||||
h.Add("Job-Name", jobName)
|
|
||||||
}
|
|
||||||
w.WriteHeader(code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func handlerGetInfo(w http.ResponseWriter, r *http.Request) {
|
|
||||||
writeHeaders(w, 200, "info")
|
|
||||||
body := `{
|
|
||||||
"Containers": 2,
|
|
||||||
"Debug": 1,
|
|
||||||
"Driver": "aufs",
|
|
||||||
"DriverStatus": [["Root Dir", "/mnt/sda1/var/lib/docker/aufs"],
|
|
||||||
["Dirs", "0"]],
|
|
||||||
"ExecutionDriver": "native-0.2",
|
|
||||||
"IPv4Forwarding": 1,
|
|
||||||
"Images": 1,
|
|
||||||
"IndexServerAddress": "https://index.docker.io/v1/",
|
|
||||||
"InitPath": "/usr/local/bin/docker",
|
|
||||||
"InitSha1": "",
|
|
||||||
"KernelVersion": "3.16.4-tinycore64",
|
|
||||||
"MemoryLimit": 1,
|
|
||||||
"NEventsListener": 0,
|
|
||||||
"NFd": 10,
|
|
||||||
"NGoroutines": 11,
|
|
||||||
"OperatingSystem": "Boot2Docker 1.3.1 (TCL 5.4); master : a083df4 - Thu Jan 01 00:00:00 UTC 1970",
|
|
||||||
"SwapLimit": 1}`
|
|
||||||
w.Write([]byte(body))
|
|
||||||
}
|
|
||||||
|
|
||||||
func handlerGetContainers(w http.ResponseWriter, r *http.Request) {
|
|
||||||
writeHeaders(w, 200, "containers")
|
|
||||||
body := `[
|
|
||||||
{
|
|
||||||
"Status": "Up 39 seconds",
|
|
||||||
"Ports": [
|
|
||||||
{
|
|
||||||
"Type": "tcp",
|
|
||||||
"PublicPort": 49163,
|
|
||||||
"PrivatePort": 8080,
|
|
||||||
"IP": "0.0.0.0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Names": [
|
|
||||||
"/trusting_heisenberg"
|
|
||||||
],
|
|
||||||
"Image": "foo:latest",
|
|
||||||
"Id": "332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688ce",
|
|
||||||
"Created": 1415720105,
|
|
||||||
"Command": "/bin/go-run"
|
|
||||||
}
|
|
||||||
]`
|
|
||||||
if v, ok := r.URL.Query()["size"]; ok {
|
|
||||||
if v[0] == "1" {
|
|
||||||
body = `[
|
|
||||||
{
|
|
||||||
"Status": "Up 39 seconds",
|
|
||||||
"Ports": [
|
|
||||||
{
|
|
||||||
"Type": "tcp",
|
|
||||||
"PublicPort": 49163,
|
|
||||||
"PrivatePort": 8080,
|
|
||||||
"IP": "0.0.0.0"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"Names": [
|
|
||||||
"/trusting_heisenberg"
|
|
||||||
],
|
|
||||||
"Image": "foo:latest",
|
|
||||||
"Id": "332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688ce",
|
|
||||||
"Created": 1415720105,
|
|
||||||
"SizeRootFs": 12345,
|
|
||||||
"SizeRW": 123,
|
|
||||||
"Command": "/bin/go-run"
|
|
||||||
}
|
|
||||||
]`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if v, ok := r.URL.Query()["filters"]; ok {
|
|
||||||
if v[0] != "{'id':['332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688ce']}" {
|
|
||||||
body = "[]"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
w.Write([]byte(body))
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleEvents(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.Write([]byte(eventsResp))
|
|
||||||
}
|
|
||||||
2
Godeps/_workspace/src/github.com/samalba/dockerclient/example_responses.go
generated
vendored
2
Godeps/_workspace/src/github.com/samalba/dockerclient/example_responses.go
generated
vendored
|
|
@ -10,4 +10,6 @@ var haproxyPullOutput = `{"status":"The image you are pulling has been verified"
|
||||||
{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"Status: Image is up to date for haproxy"}
|
{"status":"Already exists","progressDetail":{},"id":"511136ea3c5a"}{"status":"Already exists","progressDetail":{},"id":"1aeada447715"}{"status":"Already exists","progressDetail":{},"id":"479215127fa7"}{"status":"Already exists","progressDetail":{},"id":"66301eb54a7d"}{"status":"Already exists","progressDetail":{},"id":"e3990b07573f"}{"status":"Already exists","progressDetail":{},"id":"ecb4b23ca7ce"}{"status":"Already exists","progressDetail":{},"id":"f453e940c177"}{"status":"Already exists","progressDetail":{},"id":"fc5ea1bc05ab"}{"status":"Already exists","progressDetail":{},"id":"380557f8f7b3"}{"status":"Status: Image is up to date for haproxy"}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var statsResp = `{"read":"2015-02-02T17:06:08.187833376-05:00","network":{"rx_bytes":99988,"rx_packets":928,"rx_errors":0,"rx_dropped":0,"tx_bytes":1786548,"tx_packets":877,"tx_errors":0,"tx_dropped":0},"cpu_stats":{"cpu_usage":{"total_usage":170018598,"percpu_usage":[170018598],"usage_in_kernelmode":30000000,"usage_in_usermode":70000000},"system_cpu_usage":9020930000000,"throttling_data":{"periods":0,"throttled_periods":0,"throttled_time":0}},"memory_stats":{"usage":18022400,"max_usage":20541440,"stats":{"active_anon":6213632,"active_file":176128,"cache":11808768,"hierarchical_memory_limit":9223372036854775807,"hierarchical_memsw_limit":9223372036854775807,"inactive_anon":0,"inactive_file":11632640,"mapped_file":5165056,"pgfault":2535,"pgmajfault":13,"pgpgin":4293,"pgpgout":1937,"rss":6213632,"rss_huge":2097152,"swap":0,"total_active_anon":6213632,"total_active_file":176128,"total_cache":11808768,"total_inactive_anon":0,"total_inactive_file":11632640,"total_mapped_file":5165056,"total_pgfault":2535,"total_pgmajfault":13,"total_pgpgin":4293,"total_pgpgout":1937,"total_rss":6213632,"total_rss_huge":2097152,"total_swap":0,"total_unevictable":0,"unevictable":0},"failcnt":0,"limit":1041051648},"blkio_stats":{"io_service_bytes_recursive":[{"major":7,"minor":0,"op":"Read","value":28672},{"major":7,"minor":0,"op":"Write","value":0},{"major":7,"minor":0,"op":"Sync","value":0},{"major":7,"minor":0,"op":"Async","value":28672},{"major":7,"minor":0,"op":"Total","value":28672},{"major":253,"minor":0,"op":"Read","value":28672},{"major":253,"minor":0,"op":"Write","value":0},{"major":253,"minor":0,"op":"Sync","value":0},{"major":253,"minor":0,"op":"Async","value":28672},{"major":253,"minor":0,"op":"Total","value":28672},{"major":253,"minor":7,"op":"Read","value":11718656},{"major":253,"minor":7,"op":"Write","value":0},{"major":253,"minor":7,"op":"Sync","value":0},{"major":253,"minor":7,"op":"Async","value":11718656},{"major":253,"minor":7,"op":"Total","value":11718656},{"major":202,"minor":0,"op":"Read","value":0},{"major":202,"minor":0,"op":"Write","value":0},{"major":202,"minor":0,"op":"Sync","value":0},{"major":202,"minor":0,"op":"Async","value":0},{"major":202,"minor":0,"op":"Total","value":0}],"io_serviced_recursive":[{"major":7,"minor":0,"op":"Read","value":7},{"major":7,"minor":0,"op":"Write","value":0},{"major":7,"minor":0,"op":"Sync","value":0},{"major":7,"minor":0,"op":"Async","value":7},{"major":7,"minor":0,"op":"Total","value":7},{"major":253,"minor":0,"op":"Read","value":7},{"major":253,"minor":0,"op":"Write","value":0},{"major":253,"minor":0,"op":"Sync","value":0},{"major":253,"minor":0,"op":"Async","value":7},{"major":253,"minor":0,"op":"Total","value":7},{"major":253,"minor":7,"op":"Read","value":312},{"major":253,"minor":7,"op":"Write","value":0},{"major":253,"minor":7,"op":"Sync","value":0},{"major":253,"minor":7,"op":"Async","value":312},{"major":253,"minor":7,"op":"Total","value":312},{"major":202,"minor":0,"op":"Read","value":0},{"major":202,"minor":0,"op":"Write","value":0},{"major":202,"minor":0,"op":"Sync","value":0},{"major":202,"minor":0,"op":"Async","value":0},{"major":202,"minor":0,"op":"Total","value":0}],"io_queue_recursive":[],"io_service_time_recursive":[],"io_wait_time_recursive":[],"io_merged_recursive":[],"io_time_recursive":[],"sectors_recursive":[]}}`
|
||||||
|
|
||||||
var eventsResp = `{"status":"pull","id":"nginx:latest","time":1428620433}{"status":"create","id":"9b818c3b8291708fdcecd7c4086b75c222cb503be10a93d9c11040886032a48b","from":"nginx:latest","time":1428620433}{"status":"start","id":"9b818c3b8291708fdcecd7c4086b75c222cb503be10a93d9c11040886032a48b","from":"nginx:latest","time":1428620433}{"status":"die","id":"9b818c3b8291708fdcecd7c4086b75c222cb503be10a93d9c11040886032a48b","from":"nginx:latest","time":1428620442}{"status":"create","id":"352d0b412aae5a5d2b14ae9d88be59dc276602d9edb9dcc33e138e475b3e4720","from":"52.11.96.81/foobar/ubuntu:latest","time":1428620444}{"status":"start","id":"352d0b412aae5a5d2b14ae9d88be59dc276602d9edb9dcc33e138e475b3e4720","from":"52.11.96.81/foobar/ubuntu:latest","time":1428620444}{"status":"die","id":"352d0b412aae5a5d2b14ae9d88be59dc276602d9edb9dcc33e138e475b3e4720","from":"52.11.96.81/foobar/ubuntu:latest","time":1428620444}{"status":"pull","id":"debian:latest","time":1428620453}{"status":"create","id":"668887b5729946546b3072655dc6da08f0e3210111b68b704eb842adfce53f6c","from":"debian:latest","time":1428620453}{"status":"start","id":"668887b5729946546b3072655dc6da08f0e3210111b68b704eb842adfce53f6c","from":"debian:latest","time":1428620453}{"status":"die","id":"668887b5729946546b3072655dc6da08f0e3210111b68b704eb842adfce53f6c","from":"debian:latest","time":1428620453}{"status":"create","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620458}{"status":"start","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620458}{"status":"pause","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620462}{"status":"unpause","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620466}{"status":"die","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620469}`
|
var eventsResp = `{"status":"pull","id":"nginx:latest","time":1428620433}{"status":"create","id":"9b818c3b8291708fdcecd7c4086b75c222cb503be10a93d9c11040886032a48b","from":"nginx:latest","time":1428620433}{"status":"start","id":"9b818c3b8291708fdcecd7c4086b75c222cb503be10a93d9c11040886032a48b","from":"nginx:latest","time":1428620433}{"status":"die","id":"9b818c3b8291708fdcecd7c4086b75c222cb503be10a93d9c11040886032a48b","from":"nginx:latest","time":1428620442}{"status":"create","id":"352d0b412aae5a5d2b14ae9d88be59dc276602d9edb9dcc33e138e475b3e4720","from":"52.11.96.81/foobar/ubuntu:latest","time":1428620444}{"status":"start","id":"352d0b412aae5a5d2b14ae9d88be59dc276602d9edb9dcc33e138e475b3e4720","from":"52.11.96.81/foobar/ubuntu:latest","time":1428620444}{"status":"die","id":"352d0b412aae5a5d2b14ae9d88be59dc276602d9edb9dcc33e138e475b3e4720","from":"52.11.96.81/foobar/ubuntu:latest","time":1428620444}{"status":"pull","id":"debian:latest","time":1428620453}{"status":"create","id":"668887b5729946546b3072655dc6da08f0e3210111b68b704eb842adfce53f6c","from":"debian:latest","time":1428620453}{"status":"start","id":"668887b5729946546b3072655dc6da08f0e3210111b68b704eb842adfce53f6c","from":"debian:latest","time":1428620453}{"status":"die","id":"668887b5729946546b3072655dc6da08f0e3210111b68b704eb842adfce53f6c","from":"debian:latest","time":1428620453}{"status":"create","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620458}{"status":"start","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620458}{"status":"pause","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620462}{"status":"unpause","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620466}{"status":"die","id":"eb4a19ec21ab29bbbffbf3ee2e2df9d99cb749780e1eff06a591cee5ba505180","from":"nginx:latest","time":1428620469}`
|
||||||
|
|
|
||||||
39
Godeps/_workspace/src/github.com/samalba/dockerclient/examples/events.go
generated
vendored
39
Godeps/_workspace/src/github.com/samalba/dockerclient/examples/events.go
generated
vendored
|
|
@ -1,39 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/samalba/dockerclient"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func eventCallback(e *dockerclient.Event, ec chan error, args ...interface{}) {
|
|
||||||
log.Println(e)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
client *dockerclient.DockerClient
|
|
||||||
)
|
|
||||||
|
|
||||||
func waitForInterrupt() {
|
|
||||||
sigChan := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
|
|
||||||
for _ = range sigChan {
|
|
||||||
client.StopAllMonitorEvents()
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
docker, err := dockerclient.NewDockerClient(os.Getenv("DOCKER_HOST"), nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
client = docker
|
|
||||||
|
|
||||||
client.StartMonitorEvents(eventCallback, nil)
|
|
||||||
|
|
||||||
waitForInterrupt()
|
|
||||||
}
|
|
||||||
43
Godeps/_workspace/src/github.com/samalba/dockerclient/examples/stats/stats.go
generated
vendored
43
Godeps/_workspace/src/github.com/samalba/dockerclient/examples/stats/stats.go
generated
vendored
|
|
@ -1,43 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/samalba/dockerclient"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func statCallback(id string, stat *dockerclient.Stats, ec chan error, args ...interface{}) {
|
|
||||||
log.Println(stat)
|
|
||||||
}
|
|
||||||
|
|
||||||
func waitForInterrupt() {
|
|
||||||
sigChan := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
|
|
||||||
for _ = range sigChan {
|
|
||||||
os.Exit(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
docker, err := dockerclient.NewDockerClient(os.Getenv("DOCKER_HOST"), nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
containerConfig := &dockerclient.ContainerConfig{Image: "busybox", Cmd: []string{"sh"}}
|
|
||||||
containerId, err := docker.CreateContainer(containerConfig, "")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the container
|
|
||||||
err = docker.StartContainer(containerId, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
docker.StartMonitorStats(containerId, statCallback, nil)
|
|
||||||
|
|
||||||
waitForInterrupt()
|
|
||||||
}
|
|
||||||
30
Godeps/_workspace/src/github.com/samalba/dockerclient/interface.go
generated
vendored
30
Godeps/_workspace/src/github.com/samalba/dockerclient/interface.go
generated
vendored
|
|
@ -13,14 +13,24 @@ type Client interface {
|
||||||
ListContainers(all, size bool, filters string) ([]Container, error)
|
ListContainers(all, size bool, filters string) ([]Container, error)
|
||||||
InspectContainer(id string) (*ContainerInfo, error)
|
InspectContainer(id string) (*ContainerInfo, error)
|
||||||
InspectImage(id string) (*ImageInfo, error)
|
InspectImage(id string) (*ImageInfo, error)
|
||||||
CreateContainer(config *ContainerConfig, name string) (string, error)
|
CreateContainer(config *ContainerConfig, name string, authConfig *AuthConfig) (string, error)
|
||||||
ContainerLogs(id string, options *LogOptions) (io.ReadCloser, error)
|
ContainerLogs(id string, options *LogOptions) (io.ReadCloser, error)
|
||||||
ContainerChanges(id string) ([]*ContainerChanges, error)
|
ContainerChanges(id string) ([]*ContainerChanges, error)
|
||||||
Exec(config *ExecConfig) (string, error)
|
// ContainerStats takes a container ID and an optional stop channel and
|
||||||
|
// returns a StatsOrError channel. If an error is ever sent, then no
|
||||||
|
// more stats will be sent on that channel. If a stop channel is
|
||||||
|
// provided, events will stop being monitored after the stop channel is
|
||||||
|
// closed.
|
||||||
|
ContainerStats(id string, stopChan <-chan struct{}) (<-chan StatsOrError, error)
|
||||||
|
ExecCreate(config *ExecConfig) (string, error)
|
||||||
|
ExecStart(id string, config *ExecConfig) error
|
||||||
|
ExecResize(id string, width, height int) error
|
||||||
StartContainer(id string, config *HostConfig) error
|
StartContainer(id string, config *HostConfig) error
|
||||||
|
AttachContainer(id string, options *AttachOptions) (io.ReadCloser, error)
|
||||||
StopContainer(id string, timeout int) error
|
StopContainer(id string, timeout int) error
|
||||||
RestartContainer(id string, timeout int) error
|
RestartContainer(id string, timeout int) error
|
||||||
KillContainer(id, signal string) error
|
KillContainer(id, signal string) error
|
||||||
|
Wait(id string) <-chan WaitResult
|
||||||
// MonitorEvents takes options and an optional stop channel, and returns
|
// MonitorEvents takes options and an optional stop channel, and returns
|
||||||
// an EventOrError channel. If an error is ever sent, then no more
|
// an EventOrError channel. If an error is ever sent, then no more
|
||||||
// events will be sent. If a stop channel is provided, events will stop
|
// events will be sent. If a stop channel is provided, events will stop
|
||||||
|
|
@ -33,12 +43,24 @@ type Client interface {
|
||||||
TagImage(nameOrID string, repo string, tag string, force bool) error
|
TagImage(nameOrID string, repo string, tag string, force bool) error
|
||||||
Version() (*Version, error)
|
Version() (*Version, error)
|
||||||
PullImage(name string, auth *AuthConfig) error
|
PullImage(name string, auth *AuthConfig) error
|
||||||
|
PushImage(name string, tag string, auth *AuthConfig) error
|
||||||
LoadImage(reader io.Reader) error
|
LoadImage(reader io.Reader) error
|
||||||
RemoveContainer(id string, force, volumes bool) error
|
RemoveContainer(id string, force, volumes bool) error
|
||||||
ListImages() ([]*Image, error)
|
ListImages(all bool) ([]*Image, error)
|
||||||
RemoveImage(name string) ([]*ImageDelete, error)
|
RemoveImage(name string, force bool) ([]*ImageDelete, error)
|
||||||
|
SearchImages(query, registry string, auth *AuthConfig) ([]ImageSearch, error)
|
||||||
PauseContainer(name string) error
|
PauseContainer(name string) error
|
||||||
UnpauseContainer(name string) error
|
UnpauseContainer(name string) error
|
||||||
RenameContainer(oldName string, newName string) error
|
RenameContainer(oldName string, newName string) error
|
||||||
ImportImage(source string, repository string, tag string, tar io.Reader) (io.ReadCloser, error)
|
ImportImage(source string, repository string, tag string, tar io.Reader) (io.ReadCloser, error)
|
||||||
|
BuildImage(image *BuildImage) (io.ReadCloser, error)
|
||||||
|
ListVolumes() ([]*Volume, error)
|
||||||
|
RemoveVolume(name string) error
|
||||||
|
CreateVolume(request *VolumeCreateRequest) (*Volume, error)
|
||||||
|
ListNetworks(filters string) ([]*NetworkResource, error)
|
||||||
|
InspectNetwork(id string) (*NetworkResource, error)
|
||||||
|
CreateNetwork(config *NetworkCreate) (*NetworkCreateResponse, error)
|
||||||
|
ConnectNetwork(id, container string) error
|
||||||
|
DisconnectNetwork(id, container string, force bool) error
|
||||||
|
RemoveNetwork(id string) error
|
||||||
}
|
}
|
||||||
|
|
|
||||||
99
Godeps/_workspace/src/github.com/samalba/dockerclient/mockclient/mock.go
generated
vendored
99
Godeps/_workspace/src/github.com/samalba/dockerclient/mockclient/mock.go
generated
vendored
|
|
@ -35,8 +35,8 @@ func (client *MockClient) InspectImage(id string) (*dockerclient.ImageInfo, erro
|
||||||
return args.Get(0).(*dockerclient.ImageInfo), args.Error(1)
|
return args.Get(0).(*dockerclient.ImageInfo), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *MockClient) CreateContainer(config *dockerclient.ContainerConfig, name string) (string, error) {
|
func (client *MockClient) CreateContainer(config *dockerclient.ContainerConfig, name string, authConfig *dockerclient.AuthConfig) (string, error) {
|
||||||
args := client.Mock.Called(config, name)
|
args := client.Mock.Called(config, name, authConfig)
|
||||||
return args.String(0), args.Error(1)
|
return args.String(0), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,6 +50,16 @@ func (client *MockClient) ContainerChanges(id string) ([]*dockerclient.Container
|
||||||
return args.Get(0).([]*dockerclient.ContainerChanges), args.Error(1)
|
return args.Get(0).([]*dockerclient.ContainerChanges), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) ContainerStats(id string, stopChan <-chan struct{}) (<-chan dockerclient.StatsOrError, error) {
|
||||||
|
args := client.Mock.Called(id, stopChan)
|
||||||
|
return args.Get(0).(<-chan dockerclient.StatsOrError), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) AttachContainer(id string, options *dockerclient.AttachOptions) (io.ReadCloser, error) {
|
||||||
|
args := client.Mock.Called(id, options)
|
||||||
|
return args.Get(0).(io.ReadCloser), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
func (client *MockClient) StartContainer(id string, config *dockerclient.HostConfig) error {
|
func (client *MockClient) StartContainer(id string, config *dockerclient.HostConfig) error {
|
||||||
args := client.Mock.Called(id, config)
|
args := client.Mock.Called(id, config)
|
||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
|
|
@ -70,6 +80,11 @@ func (client *MockClient) KillContainer(id, signal string) error {
|
||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) Wait(id string) <-chan dockerclient.WaitResult {
|
||||||
|
args := client.Mock.Called(id)
|
||||||
|
return args.Get(0).(<-chan dockerclient.WaitResult)
|
||||||
|
}
|
||||||
|
|
||||||
func (client *MockClient) MonitorEvents(options *dockerclient.MonitorEventsOptions, stopChan <-chan struct{}) (<-chan dockerclient.EventOrError, error) {
|
func (client *MockClient) MonitorEvents(options *dockerclient.MonitorEventsOptions, stopChan <-chan struct{}) (<-chan dockerclient.EventOrError, error) {
|
||||||
args := client.Mock.Called(options, stopChan)
|
args := client.Mock.Called(options, stopChan)
|
||||||
return args.Get(0).(<-chan dockerclient.EventOrError), args.Error(1)
|
return args.Get(0).(<-chan dockerclient.EventOrError), args.Error(1)
|
||||||
|
|
@ -106,6 +121,11 @@ func (client *MockClient) PullImage(name string, auth *dockerclient.AuthConfig)
|
||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) PushImage(name string, tag string, auth *dockerclient.AuthConfig) error {
|
||||||
|
args := client.Mock.Called(name, tag, auth)
|
||||||
|
return args.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
func (client *MockClient) LoadImage(reader io.Reader) error {
|
func (client *MockClient) LoadImage(reader io.Reader) error {
|
||||||
args := client.Mock.Called(reader)
|
args := client.Mock.Called(reader)
|
||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
|
|
@ -116,16 +136,21 @@ func (client *MockClient) RemoveContainer(id string, force, volumes bool) error
|
||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *MockClient) ListImages() ([]*dockerclient.Image, error) {
|
func (client *MockClient) ListImages(all bool) ([]*dockerclient.Image, error) {
|
||||||
args := client.Mock.Called()
|
args := client.Mock.Called(all)
|
||||||
return args.Get(0).([]*dockerclient.Image), args.Error(1)
|
return args.Get(0).([]*dockerclient.Image), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *MockClient) RemoveImage(name string) ([]*dockerclient.ImageDelete, error) {
|
func (client *MockClient) RemoveImage(name string, force bool) ([]*dockerclient.ImageDelete, error) {
|
||||||
args := client.Mock.Called(name)
|
args := client.Mock.Called(name, force)
|
||||||
return args.Get(0).([]*dockerclient.ImageDelete), args.Error(1)
|
return args.Get(0).([]*dockerclient.ImageDelete), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) SearchImages(query, registry string, authConfig *dockerclient.AuthConfig) ([]dockerclient.ImageSearch, error) {
|
||||||
|
args := client.Mock.Called(query, registry, authConfig)
|
||||||
|
return args.Get(0).([]dockerclient.ImageSearch), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
func (client *MockClient) PauseContainer(name string) error {
|
func (client *MockClient) PauseContainer(name string) error {
|
||||||
args := client.Mock.Called(name)
|
args := client.Mock.Called(name)
|
||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
|
|
@ -136,11 +161,21 @@ func (client *MockClient) UnpauseContainer(name string) error {
|
||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *MockClient) Exec(config *dockerclient.ExecConfig) (string, error) {
|
func (client *MockClient) ExecCreate(config *dockerclient.ExecConfig) (string, error) {
|
||||||
args := client.Mock.Called(config)
|
args := client.Mock.Called(config)
|
||||||
return args.String(0), args.Error(1)
|
return args.String(0), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) ExecStart(id string, config *dockerclient.ExecConfig) error {
|
||||||
|
args := client.Mock.Called(id, config)
|
||||||
|
return args.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) ExecResize(id string, width, height int) error {
|
||||||
|
args := client.Mock.Called(id, width, height)
|
||||||
|
return args.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
func (client *MockClient) RenameContainer(oldName string, newName string) error {
|
func (client *MockClient) RenameContainer(oldName string, newName string) error {
|
||||||
args := client.Mock.Called(oldName, newName)
|
args := client.Mock.Called(oldName, newName)
|
||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
|
|
@ -150,3 +185,53 @@ func (client *MockClient) ImportImage(source string, repository string, tag stri
|
||||||
args := client.Mock.Called(source, repository, tag, tar)
|
args := client.Mock.Called(source, repository, tag, tar)
|
||||||
return args.Get(0).(io.ReadCloser), args.Error(1)
|
return args.Get(0).(io.ReadCloser), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) BuildImage(image *dockerclient.BuildImage) (io.ReadCloser, error) {
|
||||||
|
args := client.Mock.Called(image)
|
||||||
|
return args.Get(0).(io.ReadCloser), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) ListVolumes() ([]*dockerclient.Volume, error) {
|
||||||
|
args := client.Mock.Called()
|
||||||
|
return args.Get(0).([]*dockerclient.Volume), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) RemoveVolume(name string) error {
|
||||||
|
args := client.Mock.Called(name)
|
||||||
|
return args.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) CreateVolume(request *dockerclient.VolumeCreateRequest) (*dockerclient.Volume, error) {
|
||||||
|
args := client.Mock.Called(request)
|
||||||
|
return args.Get(0).(*dockerclient.Volume), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) ListNetworks(filters string) ([]*dockerclient.NetworkResource, error) {
|
||||||
|
args := client.Mock.Called(filters)
|
||||||
|
return args.Get(0).([]*dockerclient.NetworkResource), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) InspectNetwork(id string) (*dockerclient.NetworkResource, error) {
|
||||||
|
args := client.Mock.Called(id)
|
||||||
|
return args.Get(0).(*dockerclient.NetworkResource), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) CreateNetwork(config *dockerclient.NetworkCreate) (*dockerclient.NetworkCreateResponse, error) {
|
||||||
|
args := client.Mock.Called(config)
|
||||||
|
return args.Get(0).(*dockerclient.NetworkCreateResponse), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) ConnectNetwork(id, container string) error {
|
||||||
|
args := client.Mock.Called(id, container)
|
||||||
|
return args.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) DisconnectNetwork(id, container string, force bool) error {
|
||||||
|
args := client.Mock.Called(id, container, force)
|
||||||
|
return args.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *MockClient) RemoveNetwork(id string) error {
|
||||||
|
args := client.Mock.Called(id)
|
||||||
|
return args.Error(0)
|
||||||
|
}
|
||||||
|
|
|
||||||
38
Godeps/_workspace/src/github.com/samalba/dockerclient/tls.go
generated
vendored
Normal file
38
Godeps/_workspace/src/github.com/samalba/dockerclient/tls.go
generated
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
package dockerclient
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
|
"errors"
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TLSConfigFromCertPath returns a configuration based on PEM files in the directory
|
||||||
|
//
|
||||||
|
// path is usually what is set by the environment variable `DOCKER_CERT_PATH`,
|
||||||
|
// or `$HOME/.docker`.
|
||||||
|
func TLSConfigFromCertPath(path string) (*tls.Config, error) {
|
||||||
|
cert, err := ioutil.ReadFile(filepath.Join(path, "cert.pem"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
key, err := ioutil.ReadFile(filepath.Join(path, "key.pem"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ca, err := ioutil.ReadFile(filepath.Join(path, "ca.pem"))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tlsCert, err := tls.X509KeyPair(cert, key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tlsConfig := &tls.Config{Certificates: []tls.Certificate{tlsCert}}
|
||||||
|
tlsConfig.RootCAs = x509.NewCertPool()
|
||||||
|
if !tlsConfig.RootCAs.AppendCertsFromPEM(ca) {
|
||||||
|
return nil, errors.New("Could not add RootCA pem")
|
||||||
|
}
|
||||||
|
return tlsConfig, nil
|
||||||
|
}
|
||||||
305
Godeps/_workspace/src/github.com/samalba/dockerclient/types.go
generated
vendored
305
Godeps/_workspace/src/github.com/samalba/dockerclient/types.go
generated
vendored
|
|
@ -2,9 +2,10 @@ package dockerclient
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/units"
|
"github.com/docker/go-units"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ContainerConfig struct {
|
type ContainerConfig struct {
|
||||||
|
|
@ -22,13 +23,16 @@ type ContainerConfig struct {
|
||||||
Cmd []string
|
Cmd []string
|
||||||
Image string
|
Image string
|
||||||
Volumes map[string]struct{}
|
Volumes map[string]struct{}
|
||||||
VolumeDriver string
|
|
||||||
WorkingDir string
|
WorkingDir string
|
||||||
Entrypoint []string
|
Entrypoint []string
|
||||||
NetworkDisabled bool
|
NetworkDisabled bool
|
||||||
MacAddress string
|
MacAddress string
|
||||||
OnBuild []string
|
OnBuild []string
|
||||||
Labels map[string]string
|
Labels map[string]string
|
||||||
|
StopSignal string
|
||||||
|
|
||||||
|
// FIXME: VolumeDriver have been removed since docker 1.9
|
||||||
|
VolumeDriver string
|
||||||
|
|
||||||
// FIXME: The following fields have been removed since API v1.18
|
// FIXME: The following fields have been removed since API v1.18
|
||||||
Memory int64
|
Memory int64
|
||||||
|
|
@ -39,42 +43,70 @@ type ContainerConfig struct {
|
||||||
|
|
||||||
// This is used only by the create command
|
// This is used only by the create command
|
||||||
HostConfig HostConfig
|
HostConfig HostConfig
|
||||||
|
|
||||||
|
// Network configuration support
|
||||||
|
NetworkingConfig NetworkingConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostConfig struct {
|
type HostConfig struct {
|
||||||
Binds []string
|
Binds []string
|
||||||
ContainerIDFile string
|
ContainerIDFile string
|
||||||
LxcConf []map[string]string
|
LxcConf []map[string]string
|
||||||
Memory int64
|
Memory int64
|
||||||
MemorySwap int64
|
MemoryReservation int64
|
||||||
CpuShares int64
|
MemorySwap int64
|
||||||
CpuPeriod int64
|
KernelMemory int64
|
||||||
CpusetCpus string
|
CpuShares int64
|
||||||
CpusetMems string
|
CpuPeriod int64
|
||||||
CpuQuota int64
|
CpusetCpus string
|
||||||
BlkioWeight int64
|
CpusetMems string
|
||||||
OomKillDisable bool
|
CpuQuota int64
|
||||||
Privileged bool
|
BlkioWeight int64
|
||||||
PortBindings map[string][]PortBinding
|
OomKillDisable bool
|
||||||
Links []string
|
MemorySwappiness int64
|
||||||
PublishAllPorts bool
|
Privileged bool
|
||||||
Dns []string
|
PortBindings map[string][]PortBinding
|
||||||
DnsSearch []string
|
Links []string
|
||||||
ExtraHosts []string
|
PublishAllPorts bool
|
||||||
VolumesFrom []string
|
Dns []string
|
||||||
Devices []DeviceMapping
|
DNSOptions []string
|
||||||
NetworkMode string
|
DnsSearch []string
|
||||||
IpcMode string
|
ExtraHosts []string
|
||||||
PidMode string
|
VolumesFrom []string
|
||||||
UTSMode string
|
Devices []DeviceMapping
|
||||||
CapAdd []string
|
NetworkMode string
|
||||||
CapDrop []string
|
IpcMode string
|
||||||
RestartPolicy RestartPolicy
|
PidMode string
|
||||||
SecurityOpt []string
|
UTSMode string
|
||||||
ReadonlyRootfs bool
|
CapAdd []string
|
||||||
Ulimits []Ulimit
|
CapDrop []string
|
||||||
LogConfig LogConfig
|
GroupAdd []string
|
||||||
CgroupParent string
|
RestartPolicy RestartPolicy
|
||||||
|
SecurityOpt []string
|
||||||
|
ReadonlyRootfs bool
|
||||||
|
Ulimits []Ulimit
|
||||||
|
LogConfig LogConfig
|
||||||
|
CgroupParent string
|
||||||
|
ConsoleSize [2]int
|
||||||
|
VolumeDriver string
|
||||||
|
OomScoreAdj int
|
||||||
|
Tmpfs map[string]string
|
||||||
|
ShmSize int64
|
||||||
|
BlkioWeightDevice []WeightDevice
|
||||||
|
BlkioDeviceReadBps []ThrottleDevice
|
||||||
|
BlkioDeviceWriteBps []ThrottleDevice
|
||||||
|
BlkioDeviceReadIOps []ThrottleDevice
|
||||||
|
BlkioDeviceWriteIOps []ThrottleDevice
|
||||||
|
}
|
||||||
|
|
||||||
|
type WeightDevice struct {
|
||||||
|
Path string
|
||||||
|
Weight uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
type ThrottleDevice struct {
|
||||||
|
Path string
|
||||||
|
Rate uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeviceMapping struct {
|
type DeviceMapping struct {
|
||||||
|
|
@ -101,6 +133,14 @@ type LogOptions struct {
|
||||||
Tail int64
|
Tail int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AttachOptions struct {
|
||||||
|
Logs bool
|
||||||
|
Stream bool
|
||||||
|
Stdin bool
|
||||||
|
Stdout bool
|
||||||
|
Stderr bool
|
||||||
|
}
|
||||||
|
|
||||||
type MonitorEventsFilters struct {
|
type MonitorEventsFilters struct {
|
||||||
Event string `json:",omitempty"`
|
Event string `json:",omitempty"`
|
||||||
Image string `json:",omitempty"`
|
Image string `json:",omitempty"`
|
||||||
|
|
@ -198,6 +238,14 @@ type ImageInfo struct {
|
||||||
VirtualSize int64
|
VirtualSize int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ImageSearch struct {
|
||||||
|
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||||
|
IsOfficial bool `json:"is_official,omitempty" yaml:"is_official,omitempty"`
|
||||||
|
IsAutomated bool `json:"is_automated,omitempty" yaml:"is_automated,omitempty"`
|
||||||
|
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||||
|
StarCount int `json:"star_count,omitempty" yaml:"star_count,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type ContainerInfo struct {
|
type ContainerInfo struct {
|
||||||
Id string
|
Id string
|
||||||
Created string
|
Created string
|
||||||
|
|
@ -214,6 +262,7 @@ type ContainerInfo struct {
|
||||||
Gateway string
|
Gateway string
|
||||||
Bridge string
|
Bridge string
|
||||||
Ports map[string][]PortBinding
|
Ports map[string][]PortBinding
|
||||||
|
Networks map[string]*EndpointSettings
|
||||||
}
|
}
|
||||||
SysInitPath string
|
SysInitPath string
|
||||||
ResolvConfPath string
|
ResolvConfPath string
|
||||||
|
|
@ -233,24 +282,62 @@ type Port struct {
|
||||||
Type string
|
Type string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EndpointSettings stores the network endpoint details
|
||||||
|
type EndpointSettings struct {
|
||||||
|
// Configurations
|
||||||
|
IPAMConfig *EndpointIPAMConfig
|
||||||
|
Links []string
|
||||||
|
Aliases []string
|
||||||
|
// Operational data
|
||||||
|
NetworkID string
|
||||||
|
EndpointID string
|
||||||
|
Gateway string
|
||||||
|
IPAddress string
|
||||||
|
IPPrefixLen int
|
||||||
|
IPv6Gateway string
|
||||||
|
GlobalIPv6Address string
|
||||||
|
GlobalIPv6PrefixLen int
|
||||||
|
MacAddress string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkingConfig represents the container's networking configuration for each of its interfaces
|
||||||
|
// Carries the networink configs specified in the `docker run` and `docker network connect` commands
|
||||||
|
type NetworkingConfig struct {
|
||||||
|
EndpointsConfig map[string]*EndpointSettings // Endpoint configs for each conencting network
|
||||||
|
}
|
||||||
|
|
||||||
type Container struct {
|
type Container struct {
|
||||||
Id string
|
Id string
|
||||||
Names []string
|
Names []string
|
||||||
Image string
|
Image string
|
||||||
Command string
|
Command string
|
||||||
Created int64
|
Created int64
|
||||||
Status string
|
Status string
|
||||||
Ports []Port
|
Ports []Port
|
||||||
SizeRw int64
|
SizeRw int64
|
||||||
SizeRootFs int64
|
SizeRootFs int64
|
||||||
Labels map[string]string
|
Labels map[string]string
|
||||||
|
NetworkSettings struct {
|
||||||
|
Networks map[string]EndpointSettings
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Actor struct {
|
||||||
|
ID string
|
||||||
|
Attributes map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Event struct {
|
type Event struct {
|
||||||
Id string
|
Status string `json:"status,omitempty"`
|
||||||
Status string
|
ID string `json:"id,omitempty"`
|
||||||
From string
|
From string `json:"from,omitempty"`
|
||||||
Time int64
|
|
||||||
|
Type string
|
||||||
|
Action string
|
||||||
|
Actor Actor
|
||||||
|
|
||||||
|
Time int64 `json:"time,omitempty"`
|
||||||
|
TimeNano int64 `json:"timeNano,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Version struct {
|
type Version struct {
|
||||||
|
|
@ -271,7 +358,9 @@ type RespContainersCreate struct {
|
||||||
type Image struct {
|
type Image struct {
|
||||||
Created int64
|
Created int64
|
||||||
Id string
|
Id string
|
||||||
|
Labels map[string]string
|
||||||
ParentId string
|
ParentId string
|
||||||
|
RepoDigests []string
|
||||||
RepoTags []string
|
RepoTags []string
|
||||||
Size int64
|
Size int64
|
||||||
VirtualSize int64
|
VirtualSize int64
|
||||||
|
|
@ -318,11 +407,21 @@ type ImageDelete struct {
|
||||||
Untagged string
|
Untagged string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type StatsOrError struct {
|
||||||
|
Stats
|
||||||
|
Error error
|
||||||
|
}
|
||||||
|
|
||||||
type EventOrError struct {
|
type EventOrError struct {
|
||||||
Event
|
Event
|
||||||
Error error
|
Error error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WaitResult struct {
|
||||||
|
ExitCode int
|
||||||
|
Error error
|
||||||
|
}
|
||||||
|
|
||||||
type decodingResult struct {
|
type decodingResult struct {
|
||||||
result interface{}
|
result interface{}
|
||||||
err error
|
err error
|
||||||
|
|
@ -338,6 +437,7 @@ type ThrottlingData struct {
|
||||||
ThrottledTime uint64 `json:"throttled_time"`
|
ThrottledTime uint64 `json:"throttled_time"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All CPU stats are aggregated since container inception.
|
||||||
type CpuUsage struct {
|
type CpuUsage struct {
|
||||||
// Total CPU time consumed.
|
// Total CPU time consumed.
|
||||||
// Units: nanoseconds.
|
// Units: nanoseconds.
|
||||||
|
|
@ -415,3 +515,110 @@ type LogConfig struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Config map[string]string `json:"config"`
|
Config map[string]string `json:"config"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BuildImage struct {
|
||||||
|
Config *ConfigFile
|
||||||
|
DockerfileName string
|
||||||
|
Context io.Reader
|
||||||
|
RemoteURL string
|
||||||
|
RepoName string
|
||||||
|
SuppressOutput bool
|
||||||
|
NoCache bool
|
||||||
|
Remove bool
|
||||||
|
ForceRemove bool
|
||||||
|
Pull bool
|
||||||
|
Memory int64
|
||||||
|
MemorySwap int64
|
||||||
|
CpuShares int64
|
||||||
|
CpuPeriod int64
|
||||||
|
CpuQuota int64
|
||||||
|
CpuSetCpus string
|
||||||
|
CpuSetMems string
|
||||||
|
CgroupParent string
|
||||||
|
BuildArgs map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Volume struct {
|
||||||
|
Name string // Name is the name of the volume
|
||||||
|
Driver string // Driver is the Driver name used to create the volume
|
||||||
|
Mountpoint string // Mountpoint is the location on disk of the volume
|
||||||
|
}
|
||||||
|
|
||||||
|
type VolumesListResponse struct {
|
||||||
|
Volumes []*Volume // Volumes is the list of volumes being returned
|
||||||
|
}
|
||||||
|
|
||||||
|
type VolumeCreateRequest struct {
|
||||||
|
Name string // Name is the requested name of the volume
|
||||||
|
Driver string // Driver is the name of the driver that should be used to create the volume
|
||||||
|
DriverOpts map[string]string // DriverOpts holds the driver specific options to use for when creating the volume.
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAM represents IP Address Management
|
||||||
|
type IPAM struct {
|
||||||
|
Driver string
|
||||||
|
Options map[string]string //Per network IPAM driver options
|
||||||
|
Config []IPAMConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPAMConfig represents IPAM configurations
|
||||||
|
type IPAMConfig struct {
|
||||||
|
Subnet string `json:",omitempty"`
|
||||||
|
IPRange string `json:",omitempty"`
|
||||||
|
Gateway string `json:",omitempty"`
|
||||||
|
AuxAddress map[string]string `json:"AuxiliaryAddresses,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndpointIPAMConfig represents IPAM configurations for the endpoint
|
||||||
|
type EndpointIPAMConfig struct {
|
||||||
|
IPv4Address string `json:",omitempty"`
|
||||||
|
IPv6Address string `json:",omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkResource is the body of the "get network" http response message
|
||||||
|
type NetworkResource struct {
|
||||||
|
Name string
|
||||||
|
ID string `json:"Id"`
|
||||||
|
Scope string
|
||||||
|
Driver string
|
||||||
|
IPAM IPAM
|
||||||
|
//Internal bool
|
||||||
|
Containers map[string]EndpointResource
|
||||||
|
Options map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// EndpointResource contains network resources allocated and used for a container in a network
|
||||||
|
type EndpointResource struct {
|
||||||
|
Name string
|
||||||
|
EndpointID string
|
||||||
|
MacAddress string
|
||||||
|
IPv4Address string
|
||||||
|
IPv6Address string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkCreate is the expected body of the "create network" http request message
|
||||||
|
type NetworkCreate struct {
|
||||||
|
Name string
|
||||||
|
CheckDuplicate bool
|
||||||
|
Driver string
|
||||||
|
IPAM IPAM
|
||||||
|
Internal bool
|
||||||
|
Options map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkCreateResponse is the response message sent by the server for network create call
|
||||||
|
type NetworkCreateResponse struct {
|
||||||
|
ID string `json:"Id"`
|
||||||
|
Warning string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkConnect represents the data to be used to connect a container to the network
|
||||||
|
type NetworkConnect struct {
|
||||||
|
Container string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkDisconnect represents the data to be used to disconnect a container from the network
|
||||||
|
type NetworkDisconnect struct {
|
||||||
|
Container string
|
||||||
|
Force bool
|
||||||
|
}
|
||||||
|
|
|
||||||
12
Godeps/_workspace/src/github.com/samalba/dockerclient/utils.go
generated
vendored
12
Godeps/_workspace/src/github.com/samalba/dockerclient/utils.go
generated
vendored
|
|
@ -8,7 +8,9 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newHTTPClient(u *url.URL, tlsConfig *tls.Config, timeout time.Duration) *http.Client {
|
type tcpFunc func(*net.TCPConn, time.Duration) error
|
||||||
|
|
||||||
|
func newHTTPClient(u *url.URL, tlsConfig *tls.Config, timeout time.Duration, setUserTimeout tcpFunc) *http.Client {
|
||||||
httpTransport := &http.Transport{
|
httpTransport := &http.Transport{
|
||||||
TLSClientConfig: tlsConfig,
|
TLSClientConfig: tlsConfig,
|
||||||
}
|
}
|
||||||
|
|
@ -16,7 +18,13 @@ func newHTTPClient(u *url.URL, tlsConfig *tls.Config, timeout time.Duration) *ht
|
||||||
switch u.Scheme {
|
switch u.Scheme {
|
||||||
default:
|
default:
|
||||||
httpTransport.Dial = func(proto, addr string) (net.Conn, error) {
|
httpTransport.Dial = func(proto, addr string) (net.Conn, error) {
|
||||||
return net.DialTimeout(proto, addr, timeout)
|
conn, err := net.DialTimeout(proto, addr, timeout)
|
||||||
|
if tcpConn, ok := conn.(*net.TCPConn); ok && setUserTimeout != nil {
|
||||||
|
// Sender can break TCP connection if the remote side doesn't
|
||||||
|
// acknowledge packets within timeout
|
||||||
|
setUserTimeout(tcpConn, timeout)
|
||||||
|
}
|
||||||
|
return conn, err
|
||||||
}
|
}
|
||||||
case "unix":
|
case "unix":
|
||||||
socketPath := u.Path
|
socketPath := u.Path
|
||||||
|
|
|
||||||
14
Godeps/_workspace/src/github.com/stretchr/objx/codegen/array-access.txt
generated
vendored
14
Godeps/_workspace/src/github.com/stretchr/objx/codegen/array-access.txt
generated
vendored
|
|
@ -1,14 +0,0 @@
|
||||||
case []{1}:
|
|
||||||
a := object.([]{1})
|
|
||||||
if isSet {
|
|
||||||
a[index] = value.({1})
|
|
||||||
} else {
|
|
||||||
if index >= len(a) {
|
|
||||||
if panics {
|
|
||||||
panic(fmt.Sprintf("objx: Index %d is out of range because the []{1} only contains %d items.", index, len(a)))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return a[index]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
86
Godeps/_workspace/src/github.com/stretchr/objx/codegen/index.html
generated
vendored
86
Godeps/_workspace/src/github.com/stretchr/objx/codegen/index.html
generated
vendored
|
|
@ -1,86 +0,0 @@
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>
|
|
||||||
Codegen
|
|
||||||
</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
width: 800px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
textarea {
|
|
||||||
width: 100%;
|
|
||||||
min-height: 100px;
|
|
||||||
font-family: Courier;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<h2>
|
|
||||||
Template
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
Use <code>{x}</code> as a placeholder for each argument.
|
|
||||||
</p>
|
|
||||||
<textarea id="template"></textarea>
|
|
||||||
|
|
||||||
<h2>
|
|
||||||
Arguments (comma separated)
|
|
||||||
</h2>
|
|
||||||
<p>
|
|
||||||
One block per line
|
|
||||||
</p>
|
|
||||||
<textarea id="args"></textarea>
|
|
||||||
|
|
||||||
<h2>
|
|
||||||
Output
|
|
||||||
</h2>
|
|
||||||
<input id="go" type="button" value="Generate code" />
|
|
||||||
|
|
||||||
<textarea id="output"></textarea>
|
|
||||||
|
|
||||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
|
|
||||||
<script>
|
|
||||||
|
|
||||||
$(function(){
|
|
||||||
|
|
||||||
$("#go").click(function(){
|
|
||||||
|
|
||||||
var output = ""
|
|
||||||
var template = $("#template").val()
|
|
||||||
var args = $("#args").val()
|
|
||||||
|
|
||||||
// collect the args
|
|
||||||
var argLines = args.split("\n")
|
|
||||||
for (var line in argLines) {
|
|
||||||
|
|
||||||
var argLine = argLines[line];
|
|
||||||
var thisTemp = template
|
|
||||||
|
|
||||||
// get individual args
|
|
||||||
var args = argLine.split(",")
|
|
||||||
|
|
||||||
for (var argI in args) {
|
|
||||||
var argText = args[argI];
|
|
||||||
var argPlaceholder = "{" + argI + "}";
|
|
||||||
|
|
||||||
while (thisTemp.indexOf(argPlaceholder) > -1) {
|
|
||||||
thisTemp = thisTemp.replace(argPlaceholder, argText);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
output += thisTemp
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$("#output").val(output);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
286
Godeps/_workspace/src/github.com/stretchr/objx/codegen/template.txt
generated
vendored
286
Godeps/_workspace/src/github.com/stretchr/objx/codegen/template.txt
generated
vendored
|
|
@ -1,286 +0,0 @@
|
||||||
/*
|
|
||||||
{4} ({1} and []{1})
|
|
||||||
--------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
// {4} gets the value as a {1}, returns the optionalDefault
|
|
||||||
// value or a system default object if the value is the wrong type.
|
|
||||||
func (v *Value) {4}(optionalDefault ...{1}) {1} {
|
|
||||||
if s, ok := v.data.({1}); ok {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
if len(optionalDefault) == 1 {
|
|
||||||
return optionalDefault[0]
|
|
||||||
}
|
|
||||||
return {3}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must{4} gets the value as a {1}.
|
|
||||||
//
|
|
||||||
// Panics if the object is not a {1}.
|
|
||||||
func (v *Value) Must{4}() {1} {
|
|
||||||
return v.data.({1})
|
|
||||||
}
|
|
||||||
|
|
||||||
// {4}Slice gets the value as a []{1}, returns the optionalDefault
|
|
||||||
// value or nil if the value is not a []{1}.
|
|
||||||
func (v *Value) {4}Slice(optionalDefault ...[]{1}) []{1} {
|
|
||||||
if s, ok := v.data.([]{1}); ok {
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
if len(optionalDefault) == 1 {
|
|
||||||
return optionalDefault[0]
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must{4}Slice gets the value as a []{1}.
|
|
||||||
//
|
|
||||||
// Panics if the object is not a []{1}.
|
|
||||||
func (v *Value) Must{4}Slice() []{1} {
|
|
||||||
return v.data.([]{1})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is{4} gets whether the object contained is a {1} or not.
|
|
||||||
func (v *Value) Is{4}() bool {
|
|
||||||
_, ok := v.data.({1})
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is{4}Slice gets whether the object contained is a []{1} or not.
|
|
||||||
func (v *Value) Is{4}Slice() bool {
|
|
||||||
_, ok := v.data.([]{1})
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// Each{4} calls the specified callback for each object
|
|
||||||
// in the []{1}.
|
|
||||||
//
|
|
||||||
// Panics if the object is the wrong type.
|
|
||||||
func (v *Value) Each{4}(callback func(int, {1}) bool) *Value {
|
|
||||||
|
|
||||||
for index, val := range v.Must{4}Slice() {
|
|
||||||
carryon := callback(index, val)
|
|
||||||
if carryon == false {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return v
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Where{4} uses the specified decider function to select items
|
|
||||||
// from the []{1}. The object contained in the result will contain
|
|
||||||
// only the selected items.
|
|
||||||
func (v *Value) Where{4}(decider func(int, {1}) bool) *Value {
|
|
||||||
|
|
||||||
var selected []{1}
|
|
||||||
|
|
||||||
v.Each{4}(func(index int, val {1}) bool {
|
|
||||||
shouldSelect := decider(index, val)
|
|
||||||
if shouldSelect == false {
|
|
||||||
selected = append(selected, val)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
return &Value{data:selected}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Group{4} uses the specified grouper function to group the items
|
|
||||||
// keyed by the return of the grouper. The object contained in the
|
|
||||||
// result will contain a map[string][]{1}.
|
|
||||||
func (v *Value) Group{4}(grouper func(int, {1}) string) *Value {
|
|
||||||
|
|
||||||
groups := make(map[string][]{1})
|
|
||||||
|
|
||||||
v.Each{4}(func(index int, val {1}) bool {
|
|
||||||
group := grouper(index, val)
|
|
||||||
if _, ok := groups[group]; !ok {
|
|
||||||
groups[group] = make([]{1}, 0)
|
|
||||||
}
|
|
||||||
groups[group] = append(groups[group], val)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
return &Value{data:groups}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace{4} uses the specified function to replace each {1}s
|
|
||||||
// by iterating each item. The data in the returned result will be a
|
|
||||||
// []{1} containing the replaced items.
|
|
||||||
func (v *Value) Replace{4}(replacer func(int, {1}) {1}) *Value {
|
|
||||||
|
|
||||||
arr := v.Must{4}Slice()
|
|
||||||
replaced := make([]{1}, len(arr))
|
|
||||||
|
|
||||||
v.Each{4}(func(index int, val {1}) bool {
|
|
||||||
replaced[index] = replacer(index, val)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
return &Value{data:replaced}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect{4} uses the specified collector function to collect a value
|
|
||||||
// for each of the {1}s in the slice. The data returned will be a
|
|
||||||
// []interface{}.
|
|
||||||
func (v *Value) Collect{4}(collector func(int, {1}) interface{}) *Value {
|
|
||||||
|
|
||||||
arr := v.Must{4}Slice()
|
|
||||||
collected := make([]interface{}, len(arr))
|
|
||||||
|
|
||||||
v.Each{4}(func(index int, val {1}) bool {
|
|
||||||
collected[index] = collector(index, val)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
return &Value{data:collected}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ************************************************************
|
|
||||||
// TESTS
|
|
||||||
// ************************************************************
|
|
||||||
|
|
||||||
func Test{4}(t *testing.T) {
|
|
||||||
|
|
||||||
val := {1}( {2} )
|
|
||||||
m := map[string]interface{}{"value": val, "nothing": nil}
|
|
||||||
assert.Equal(t, val, New(m).Get("value").{4}())
|
|
||||||
assert.Equal(t, val, New(m).Get("value").Must{4}())
|
|
||||||
assert.Equal(t, {1}({3}), New(m).Get("nothing").{4}())
|
|
||||||
assert.Equal(t, val, New(m).Get("nothing").{4}({2}))
|
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
|
||||||
New(m).Get("age").Must{4}()
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test{4}Slice(t *testing.T) {
|
|
||||||
|
|
||||||
val := {1}( {2} )
|
|
||||||
m := map[string]interface{}{"value": []{1}{ val }, "nothing": nil}
|
|
||||||
assert.Equal(t, val, New(m).Get("value").{4}Slice()[0])
|
|
||||||
assert.Equal(t, val, New(m).Get("value").Must{4}Slice()[0])
|
|
||||||
assert.Equal(t, []{1}(nil), New(m).Get("nothing").{4}Slice())
|
|
||||||
assert.Equal(t, val, New(m).Get("nothing").{4}Slice( []{1}{ {1}({2}) } )[0])
|
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
|
||||||
New(m).Get("nothing").Must{4}Slice()
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIs{4}(t *testing.T) {
|
|
||||||
|
|
||||||
var v *Value
|
|
||||||
|
|
||||||
v = &Value{data: {1}({2})}
|
|
||||||
assert.True(t, v.Is{4}())
|
|
||||||
|
|
||||||
v = &Value{data: []{1}{ {1}({2}) }}
|
|
||||||
assert.True(t, v.Is{4}Slice())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEach{4}(t *testing.T) {
|
|
||||||
|
|
||||||
v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
|
|
||||||
count := 0
|
|
||||||
replacedVals := make([]{1}, 0)
|
|
||||||
assert.Equal(t, v, v.Each{4}(func(i int, val {1}) bool {
|
|
||||||
|
|
||||||
count++
|
|
||||||
replacedVals = append(replacedVals, val)
|
|
||||||
|
|
||||||
// abort early
|
|
||||||
if i == 2 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
|
|
||||||
}))
|
|
||||||
|
|
||||||
assert.Equal(t, count, 3)
|
|
||||||
assert.Equal(t, replacedVals[0], v.Must{4}Slice()[0])
|
|
||||||
assert.Equal(t, replacedVals[1], v.Must{4}Slice()[1])
|
|
||||||
assert.Equal(t, replacedVals[2], v.Must{4}Slice()[2])
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWhere{4}(t *testing.T) {
|
|
||||||
|
|
||||||
v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
|
|
||||||
|
|
||||||
selected := v.Where{4}(func(i int, val {1}) bool {
|
|
||||||
return i%2==0
|
|
||||||
}).Must{4}Slice()
|
|
||||||
|
|
||||||
assert.Equal(t, 3, len(selected))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGroup{4}(t *testing.T) {
|
|
||||||
|
|
||||||
v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
|
|
||||||
|
|
||||||
grouped := v.Group{4}(func(i int, val {1}) string {
|
|
||||||
return fmt.Sprintf("%v", i%2==0)
|
|
||||||
}).data.(map[string][]{1})
|
|
||||||
|
|
||||||
assert.Equal(t, 2, len(grouped))
|
|
||||||
assert.Equal(t, 3, len(grouped["true"]))
|
|
||||||
assert.Equal(t, 3, len(grouped["false"]))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReplace{4}(t *testing.T) {
|
|
||||||
|
|
||||||
v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
|
|
||||||
|
|
||||||
rawArr := v.Must{4}Slice()
|
|
||||||
|
|
||||||
replaced := v.Replace{4}(func(index int, val {1}) {1} {
|
|
||||||
if index < len(rawArr)-1 {
|
|
||||||
return rawArr[index+1]
|
|
||||||
}
|
|
||||||
return rawArr[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
replacedArr := replaced.Must{4}Slice()
|
|
||||||
if assert.Equal(t, 6, len(replacedArr)) {
|
|
||||||
assert.Equal(t, replacedArr[0], rawArr[1])
|
|
||||||
assert.Equal(t, replacedArr[1], rawArr[2])
|
|
||||||
assert.Equal(t, replacedArr[2], rawArr[3])
|
|
||||||
assert.Equal(t, replacedArr[3], rawArr[4])
|
|
||||||
assert.Equal(t, replacedArr[4], rawArr[5])
|
|
||||||
assert.Equal(t, replacedArr[5], rawArr[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCollect{4}(t *testing.T) {
|
|
||||||
|
|
||||||
v := &Value{data: []{1}{ {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}), {1}({2}) }}
|
|
||||||
|
|
||||||
collected := v.Collect{4}(func(index int, val {1}) interface{} {
|
|
||||||
return index
|
|
||||||
})
|
|
||||||
|
|
||||||
collectedArr := collected.MustInterSlice()
|
|
||||||
if assert.Equal(t, 6, len(collectedArr)) {
|
|
||||||
assert.Equal(t, collectedArr[0], 0)
|
|
||||||
assert.Equal(t, collectedArr[1], 1)
|
|
||||||
assert.Equal(t, collectedArr[2], 2)
|
|
||||||
assert.Equal(t, collectedArr[3], 3)
|
|
||||||
assert.Equal(t, collectedArr[4], 4)
|
|
||||||
assert.Equal(t, collectedArr[5], 5)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
20
Godeps/_workspace/src/github.com/stretchr/objx/codegen/types_list.txt
generated
vendored
20
Godeps/_workspace/src/github.com/stretchr/objx/codegen/types_list.txt
generated
vendored
|
|
@ -1,20 +0,0 @@
|
||||||
Interface,interface{},"something",nil,Inter
|
|
||||||
Map,map[string]interface{},map[string]interface{}{"name":"Tyler"},nil,MSI
|
|
||||||
ObjxMap,(Map),New(1),New(nil),ObjxMap
|
|
||||||
Bool,bool,true,false,Bool
|
|
||||||
String,string,"hello","",Str
|
|
||||||
Int,int,1,0,Int
|
|
||||||
Int8,int8,1,0,Int8
|
|
||||||
Int16,int16,1,0,Int16
|
|
||||||
Int32,int32,1,0,Int32
|
|
||||||
Int64,int64,1,0,Int64
|
|
||||||
Uint,uint,1,0,Uint
|
|
||||||
Uint8,uint8,1,0,Uint8
|
|
||||||
Uint16,uint16,1,0,Uint16
|
|
||||||
Uint32,uint32,1,0,Uint32
|
|
||||||
Uint64,uint64,1,0,Uint64
|
|
||||||
Uintptr,uintptr,1,0,Uintptr
|
|
||||||
Float32,float32,1,0,Float32
|
|
||||||
Float64,float64,1,0,Float64
|
|
||||||
Complex64,complex64,1,0,Complex64
|
|
||||||
Complex128,complex128,1,0,Complex128
|
|
||||||
43
Godeps/_workspace/src/github.com/stretchr/objx/value.go
generated
vendored
43
Godeps/_workspace/src/github.com/stretchr/objx/value.go
generated
vendored
|
|
@ -1,5 +1,10 @@
|
||||||
package objx
|
package objx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
// Value provides methods for extracting interface{} data in various
|
// Value provides methods for extracting interface{} data in various
|
||||||
// types.
|
// types.
|
||||||
type Value struct {
|
type Value struct {
|
||||||
|
|
@ -11,3 +16,41 @@ type Value struct {
|
||||||
func (v *Value) Data() interface{} {
|
func (v *Value) Data() interface{} {
|
||||||
return v.data
|
return v.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// String returns the value always as a string
|
||||||
|
func (v *Value) String() string {
|
||||||
|
switch {
|
||||||
|
case v.IsStr():
|
||||||
|
return v.Str()
|
||||||
|
case v.IsBool():
|
||||||
|
return strconv.FormatBool(v.Bool())
|
||||||
|
case v.IsFloat32():
|
||||||
|
return strconv.FormatFloat(float64(v.Float32()), 'f', -1, 32)
|
||||||
|
case v.IsFloat64():
|
||||||
|
return strconv.FormatFloat(v.Float64(), 'f', -1, 64)
|
||||||
|
case v.IsInt():
|
||||||
|
return strconv.FormatInt(int64(v.Int()), 10)
|
||||||
|
case v.IsInt():
|
||||||
|
return strconv.FormatInt(int64(v.Int()), 10)
|
||||||
|
case v.IsInt8():
|
||||||
|
return strconv.FormatInt(int64(v.Int8()), 10)
|
||||||
|
case v.IsInt16():
|
||||||
|
return strconv.FormatInt(int64(v.Int16()), 10)
|
||||||
|
case v.IsInt32():
|
||||||
|
return strconv.FormatInt(int64(v.Int32()), 10)
|
||||||
|
case v.IsInt64():
|
||||||
|
return strconv.FormatInt(v.Int64(), 10)
|
||||||
|
case v.IsUint():
|
||||||
|
return strconv.FormatUint(uint64(v.Uint()), 10)
|
||||||
|
case v.IsUint8():
|
||||||
|
return strconv.FormatUint(uint64(v.Uint8()), 10)
|
||||||
|
case v.IsUint16():
|
||||||
|
return strconv.FormatUint(uint64(v.Uint16()), 10)
|
||||||
|
case v.IsUint32():
|
||||||
|
return strconv.FormatUint(uint64(v.Uint32()), 10)
|
||||||
|
case v.IsUint64():
|
||||||
|
return strconv.FormatUint(v.Uint64(), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%#v", v.Data())
|
||||||
|
}
|
||||||
|
|
|
||||||
65
Godeps/_workspace/src/github.com/stretchr/objx/value_test.go
generated
vendored
65
Godeps/_workspace/src/github.com/stretchr/objx/value_test.go
generated
vendored
|
|
@ -1 +1,66 @@
|
||||||
package objx
|
package objx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestStringTypeString(t *testing.T) {
|
||||||
|
m := New(map[string]interface{}{"string": "foo"})
|
||||||
|
assert.Equal(t, "foo", m.Get("string").String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringTypeBool(t *testing.T) {
|
||||||
|
m := New(map[string]interface{}{"bool": true})
|
||||||
|
assert.Equal(t, "true", m.Get("bool").String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringTypeInt(t *testing.T) {
|
||||||
|
m := New(map[string]interface{}{
|
||||||
|
"int": int(1),
|
||||||
|
"int8": int8(8),
|
||||||
|
"int16": int16(16),
|
||||||
|
"int32": int32(32),
|
||||||
|
"int64": int64(64),
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(t, "1", m.Get("int").String())
|
||||||
|
assert.Equal(t, "8", m.Get("int8").String())
|
||||||
|
assert.Equal(t, "16", m.Get("int16").String())
|
||||||
|
assert.Equal(t, "32", m.Get("int32").String())
|
||||||
|
assert.Equal(t, "64", m.Get("int64").String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringTypeUint(t *testing.T) {
|
||||||
|
m := New(map[string]interface{}{
|
||||||
|
"uint": uint(1),
|
||||||
|
"uint8": uint8(8),
|
||||||
|
"uint16": uint16(16),
|
||||||
|
"uint32": uint32(32),
|
||||||
|
"uint64": uint64(64),
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(t, "1", m.Get("uint").String())
|
||||||
|
assert.Equal(t, "8", m.Get("uint8").String())
|
||||||
|
assert.Equal(t, "16", m.Get("uint16").String())
|
||||||
|
assert.Equal(t, "32", m.Get("uint32").String())
|
||||||
|
assert.Equal(t, "64", m.Get("uint64").String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringTypeFloat(t *testing.T) {
|
||||||
|
m := New(map[string]interface{}{
|
||||||
|
"float32": float32(32.32),
|
||||||
|
"float64": float64(64.64),
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(t, "32.32", m.Get("float32").String())
|
||||||
|
assert.Equal(t, "64.64", m.Get("float64").String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStringTypeOther(t *testing.T) {
|
||||||
|
m := New(map[string]interface{}{
|
||||||
|
"other": []string{"foo", "bar"},
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(t, "[]string{\"foo\", \"bar\"}", m.Get("other").String())
|
||||||
|
}
|
||||||
|
|
|
||||||
22
Godeps/_workspace/src/github.com/stretchr/testify/LICENCE.txt
generated
vendored
Normal file
22
Godeps/_workspace/src/github.com/stretchr/testify/LICENCE.txt
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell
|
||||||
|
|
||||||
|
Please consider promoting this project if you find it useful.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without restriction,
|
||||||
|
including without limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
|
||||||
|
OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
22
Godeps/_workspace/src/github.com/stretchr/testify/LICENSE
generated
vendored
Normal file
22
Godeps/_workspace/src/github.com/stretchr/testify/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell
|
||||||
|
|
||||||
|
Please consider promoting this project if you find it useful.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person
|
||||||
|
obtaining a copy of this software and associated documentation
|
||||||
|
files (the "Software"), to deal in the Software without restriction,
|
||||||
|
including without limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
|
||||||
|
OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
||||||
|
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
387
Godeps/_workspace/src/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
Normal file
387
Godeps/_workspace/src/github.com/stretchr/testify/assert/assertion_forward.go
generated
vendored
Normal file
|
|
@ -0,0 +1,387 @@
|
||||||
|
/*
|
||||||
|
* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen
|
||||||
|
* THIS FILE MUST NOT BE EDITED BY HAND
|
||||||
|
*/
|
||||||
|
|
||||||
|
package assert
|
||||||
|
|
||||||
|
import (
|
||||||
|
|
||||||
|
http "net/http"
|
||||||
|
url "net/url"
|
||||||
|
time "time"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// Condition uses a Comparison to assert a complex condition.
|
||||||
|
func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
|
||||||
|
return Condition(a.t, comp, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Contains asserts that the specified string, list(array, slice...) or map contains the
|
||||||
|
// specified substring or element.
|
||||||
|
//
|
||||||
|
// a.Contains("Hello World", "World", "But 'Hello World' does contain 'World'")
|
||||||
|
// a.Contains(["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
|
||||||
|
// a.Contains({"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return Contains(a.t, s, contains, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
|
||||||
|
// a slice or a channel with len == 0.
|
||||||
|
//
|
||||||
|
// a.Empty(obj)
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return Empty(a.t, object, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Equal asserts that two objects are equal.
|
||||||
|
//
|
||||||
|
// a.Equal(123, 123, "123 and 123 should be equal")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return Equal(a.t, expected, actual, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// EqualError asserts that a function returned an error (i.e. not `nil`)
|
||||||
|
// and that it is equal to the provided error.
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// if assert.Error(t, err, "An error was expected") {
|
||||||
|
// assert.Equal(t, err, expectedError)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
|
||||||
|
return EqualError(a.t, theError, errString, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// EqualValues asserts that two objects are equal or convertable to the same types
|
||||||
|
// and equal.
|
||||||
|
//
|
||||||
|
// a.EqualValues(uint32(123), int32(123), "123 and 123 should be equal")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return EqualValues(a.t, expected, actual, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Error asserts that a function returned an error (i.e. not `nil`).
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// if a.Error(err, "An error was expected") {
|
||||||
|
// assert.Equal(t, err, expectedError)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool {
|
||||||
|
return Error(a.t, err, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Exactly asserts that two objects are equal is value and type.
|
||||||
|
//
|
||||||
|
// a.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return Exactly(a.t, expected, actual, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Fail reports a failure through
|
||||||
|
func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
|
||||||
|
return Fail(a.t, failureMessage, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// FailNow fails test
|
||||||
|
func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool {
|
||||||
|
return FailNow(a.t, failureMessage, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// False asserts that the specified value is false.
|
||||||
|
//
|
||||||
|
// a.False(myBool, "myBool should be false")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
|
||||||
|
return False(a.t, value, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// HTTPBodyContains asserts that a specified handler returns a
|
||||||
|
// body that contains a string.
|
||||||
|
//
|
||||||
|
// a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
|
||||||
|
return HTTPBodyContains(a.t, handler, method, url, values, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// HTTPBodyNotContains asserts that a specified handler returns a
|
||||||
|
// body that does not contain a string.
|
||||||
|
//
|
||||||
|
// a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}) bool {
|
||||||
|
return HTTPBodyNotContains(a.t, handler, method, url, values, str)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// HTTPError asserts that a specified handler returns an error status code.
|
||||||
|
//
|
||||||
|
// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values) bool {
|
||||||
|
return HTTPError(a.t, handler, method, url, values)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// HTTPRedirect asserts that a specified handler returns a redirect status code.
|
||||||
|
//
|
||||||
|
// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values) bool {
|
||||||
|
return HTTPRedirect(a.t, handler, method, url, values)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// HTTPSuccess asserts that a specified handler returns a success status code.
|
||||||
|
//
|
||||||
|
// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values) bool {
|
||||||
|
return HTTPSuccess(a.t, handler, method, url, values)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Implements asserts that an object is implemented by the specified interface.
|
||||||
|
//
|
||||||
|
// a.Implements((*MyInterface)(nil), new(MyObject), "MyObject")
|
||||||
|
func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return Implements(a.t, interfaceObject, object, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// InDelta asserts that the two numerals are within delta of each other.
|
||||||
|
//
|
||||||
|
// a.InDelta(math.Pi, (22 / 7.0), 0.01)
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||||
|
return InDelta(a.t, expected, actual, delta, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// InDeltaSlice is the same as InDelta, except it compares two slices.
|
||||||
|
func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||||
|
return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// InEpsilon asserts that expected and actual have a relative error less than epsilon
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||||
|
return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// InEpsilonSlice is the same as InEpsilon, except it compares two slices.
|
||||||
|
func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
||||||
|
return InEpsilonSlice(a.t, expected, actual, delta, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// IsType asserts that the specified objects are of the same type.
|
||||||
|
func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return IsType(a.t, expectedType, object, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// JSONEq asserts that two JSON strings are equivalent.
|
||||||
|
//
|
||||||
|
// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool {
|
||||||
|
return JSONEq(a.t, expected, actual, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Len asserts that the specified object has specific length.
|
||||||
|
// Len also fails if the object has a type that len() not accept.
|
||||||
|
//
|
||||||
|
// a.Len(mySlice, 3, "The size of slice is not 3")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
|
||||||
|
return Len(a.t, object, length, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Nil asserts that the specified object is nil.
|
||||||
|
//
|
||||||
|
// a.Nil(err, "err should be nothing")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return Nil(a.t, object, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NoError asserts that a function returned no error (i.e. `nil`).
|
||||||
|
//
|
||||||
|
// actualObj, err := SomeFunction()
|
||||||
|
// if a.NoError(err) {
|
||||||
|
// assert.Equal(t, actualObj, expectedObj)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool {
|
||||||
|
return NoError(a.t, err, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
|
||||||
|
// specified substring or element.
|
||||||
|
//
|
||||||
|
// a.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
|
||||||
|
// a.NotContains(["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
|
||||||
|
// a.NotContains({"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return NotContains(a.t, s, contains, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
||||||
|
// a slice or a channel with len == 0.
|
||||||
|
//
|
||||||
|
// if a.NotEmpty(obj) {
|
||||||
|
// assert.Equal(t, "two", obj[1])
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return NotEmpty(a.t, object, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NotEqual asserts that the specified values are NOT equal.
|
||||||
|
//
|
||||||
|
// a.NotEqual(obj1, obj2, "two objects shouldn't be equal")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return NotEqual(a.t, expected, actual, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NotNil asserts that the specified object is not nil.
|
||||||
|
//
|
||||||
|
// a.NotNil(err, "err should be something")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return NotNil(a.t, object, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
|
||||||
|
//
|
||||||
|
// a.NotPanics(func(){
|
||||||
|
// RemainCalm()
|
||||||
|
// }, "Calling RemainCalm() should NOT panic")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||||
|
return NotPanics(a.t, f, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NotRegexp asserts that a specified regexp does not match a string.
|
||||||
|
//
|
||||||
|
// a.NotRegexp(regexp.MustCompile("starts"), "it's starting")
|
||||||
|
// a.NotRegexp("^start", "it's not starting")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return NotRegexp(a.t, rx, str, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NotZero asserts that i is not the zero value for its type and returns the truth.
|
||||||
|
func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return NotZero(a.t, i, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Panics asserts that the code inside the specified PanicTestFunc panics.
|
||||||
|
//
|
||||||
|
// a.Panics(func(){
|
||||||
|
// GoCrazy()
|
||||||
|
// }, "Calling GoCrazy() should panic")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
||||||
|
return Panics(a.t, f, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Regexp asserts that a specified regexp matches a string.
|
||||||
|
//
|
||||||
|
// a.Regexp(regexp.MustCompile("start"), "it's starting")
|
||||||
|
// a.Regexp("start...$", "it's not starting")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return Regexp(a.t, rx, str, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// True asserts that the specified value is true.
|
||||||
|
//
|
||||||
|
// a.True(myBool, "myBool should be true")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
|
||||||
|
return True(a.t, value, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// WithinDuration asserts that the two times are within duration delta of each other.
|
||||||
|
//
|
||||||
|
// a.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
|
||||||
|
return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Zero asserts that i is the zero value for its type and returns the truth.
|
||||||
|
func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
return Zero(a.t, i, msgAndArgs...)
|
||||||
|
}
|
||||||
4
Godeps/_workspace/src/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
generated
vendored
Normal file
4
Godeps/_workspace/src/github.com/stretchr/testify/assert/assertion_forward.go.tmpl
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
{{.CommentWithoutT "a"}}
|
||||||
|
func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool {
|
||||||
|
return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}})
|
||||||
|
}
|
||||||
239
Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go
generated
vendored
239
Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions.go
generated
vendored
|
|
@ -3,6 +3,7 @@ package assert
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
@ -12,6 +13,9 @@ import (
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/pmezard/go-difflib/difflib"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestingT is an interface wrapper around *testing.T
|
// TestingT is an interface wrapper around *testing.T
|
||||||
|
|
@ -35,11 +39,7 @@ func ObjectsAreEqual(expected, actual interface{}) bool {
|
||||||
return expected == actual
|
return expected == actual
|
||||||
}
|
}
|
||||||
|
|
||||||
if reflect.DeepEqual(expected, actual) {
|
return reflect.DeepEqual(expected, actual)
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,12 +51,13 @@ func ObjectsAreEqualValues(expected, actual interface{}) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
actualType := reflect.TypeOf(actual)
|
actualType := reflect.TypeOf(actual)
|
||||||
|
if actualType == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
expectedValue := reflect.ValueOf(expected)
|
expectedValue := reflect.ValueOf(expected)
|
||||||
if expectedValue.Type().ConvertibleTo(actualType) {
|
if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) {
|
||||||
// Attempt comparison after type conversion
|
// Attempt comparison after type conversion
|
||||||
if reflect.DeepEqual(actual, expectedValue.Convert(actualType).Interface()) {
|
return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual)
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|
@ -180,6 +181,28 @@ func indentMessageLines(message string, tabs int) string {
|
||||||
return outBuf.String()
|
return outBuf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type failNower interface {
|
||||||
|
FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FailNow fails test
|
||||||
|
func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
|
||||||
|
Fail(t, failureMessage, msgAndArgs...)
|
||||||
|
|
||||||
|
// We cannot extend TestingT with FailNow() and
|
||||||
|
// maintain backwards compatibility, so we fallback
|
||||||
|
// to panicking when FailNow is not available in
|
||||||
|
// TestingT.
|
||||||
|
// See issue #263
|
||||||
|
|
||||||
|
if t, ok := t.(failNower); ok {
|
||||||
|
t.FailNow()
|
||||||
|
} else {
|
||||||
|
panic("test failed and t is missing `FailNow()`")
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Fail reports a failure through
|
// Fail reports a failure through
|
||||||
func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
|
func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool {
|
||||||
|
|
||||||
|
|
@ -213,7 +236,7 @@ func Implements(t TestingT, interfaceObject interface{}, object interface{}, msg
|
||||||
interfaceType := reflect.TypeOf(interfaceObject).Elem()
|
interfaceType := reflect.TypeOf(interfaceObject).Elem()
|
||||||
|
|
||||||
if !reflect.TypeOf(object).Implements(interfaceType) {
|
if !reflect.TypeOf(object).Implements(interfaceType) {
|
||||||
return Fail(t, fmt.Sprintf("Object must implement %v", interfaceType), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
@ -238,8 +261,9 @@ func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs
|
||||||
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
|
||||||
if !ObjectsAreEqual(expected, actual) {
|
if !ObjectsAreEqual(expected, actual) {
|
||||||
|
diff := diff(expected, actual)
|
||||||
return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
|
return Fail(t, fmt.Sprintf("Not equal: %#v (expected)\n"+
|
||||||
" != %#v (actual)", expected, actual), msgAndArgs...)
|
" != %#v (actual)%s", expected, actual, diff), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
@ -274,7 +298,7 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
|
||||||
bType := reflect.TypeOf(actual)
|
bType := reflect.TypeOf(actual)
|
||||||
|
|
||||||
if aType != bType {
|
if aType != bType {
|
||||||
return Fail(t, "Types expected to match exactly", "%v != %v", aType, bType)
|
return Fail(t, fmt.Sprintf("Types expected to match exactly\n\r\t%v != %v", aType, bType), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return Equal(t, expected, actual, msgAndArgs...)
|
return Equal(t, expected, actual, msgAndArgs...)
|
||||||
|
|
@ -287,24 +311,10 @@ func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if !isNil(object) {
|
||||||
success := true
|
return true
|
||||||
|
|
||||||
if object == nil {
|
|
||||||
success = false
|
|
||||||
} else {
|
|
||||||
value := reflect.ValueOf(object)
|
|
||||||
kind := value.Kind()
|
|
||||||
if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
|
|
||||||
success = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return Fail(t, "Expected value not to be nil.", msgAndArgs...)
|
||||||
if !success {
|
|
||||||
Fail(t, "Expected value not to be nil.", msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return success
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// isNil checks if a specified object is nil or not, without Failing.
|
// isNil checks if a specified object is nil or not, without Failing.
|
||||||
|
|
@ -334,7 +344,7 @@ func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
var zeros = []interface{}{
|
var numericZeros = []interface{}{
|
||||||
int(0),
|
int(0),
|
||||||
int8(0),
|
int8(0),
|
||||||
int16(0),
|
int16(0),
|
||||||
|
|
@ -360,7 +370,7 @@ func isEmpty(object interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range zeros {
|
for _, v := range numericZeros {
|
||||||
if object == v {
|
if object == v {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -375,8 +385,16 @@ func isEmpty(object interface{}) bool {
|
||||||
{
|
{
|
||||||
return (objValue.Len() == 0)
|
return (objValue.Len() == 0)
|
||||||
}
|
}
|
||||||
|
case reflect.Struct:
|
||||||
|
switch object.(type) {
|
||||||
|
case time.Time:
|
||||||
|
return object.(time.Time).IsZero()
|
||||||
|
}
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
{
|
{
|
||||||
|
if objValue.IsNil() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
switch object.(type) {
|
switch object.(type) {
|
||||||
case *time.Time:
|
case *time.Time:
|
||||||
return object.(*time.Time).IsZero()
|
return object.(*time.Time).IsZero()
|
||||||
|
|
@ -391,7 +409,7 @@ func isEmpty(object interface{}) bool {
|
||||||
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
|
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either
|
||||||
// a slice or a channel with len == 0.
|
// a slice or a channel with len == 0.
|
||||||
//
|
//
|
||||||
// assert.Empty(t, obj)
|
// assert.Empty(t, obj)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
|
@ -408,9 +426,9 @@ func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either
|
||||||
// a slice or a channel with len == 0.
|
// a slice or a channel with len == 0.
|
||||||
//
|
//
|
||||||
// if assert.NotEmpty(t, obj) {
|
// if assert.NotEmpty(t, obj) {
|
||||||
// assert.Equal(t, "two", obj[1])
|
// assert.Equal(t, "two", obj[1])
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
|
@ -469,7 +487,7 @@ func True(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// False asserts that the specified value is true.
|
// False asserts that the specified value is false.
|
||||||
//
|
//
|
||||||
// assert.False(t, myBool, "myBool should be false")
|
// assert.False(t, myBool, "myBool should be false")
|
||||||
//
|
//
|
||||||
|
|
@ -492,7 +510,7 @@ func False(t TestingT, value bool, msgAndArgs ...interface{}) bool {
|
||||||
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
|
||||||
if ObjectsAreEqual(expected, actual) {
|
if ObjectsAreEqual(expected, actual) {
|
||||||
return Fail(t, "Should not be equal", msgAndArgs...)
|
return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
@ -518,6 +536,16 @@ func includeElement(list interface{}, element interface{}) (ok, found bool) {
|
||||||
return true, strings.Contains(listValue.String(), elementValue.String())
|
return true, strings.Contains(listValue.String(), elementValue.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if reflect.TypeOf(list).Kind() == reflect.Map {
|
||||||
|
mapKeys := listValue.MapKeys()
|
||||||
|
for i := 0; i < len(mapKeys); i++ {
|
||||||
|
if ObjectsAreEqual(mapKeys[i].Interface(), element) {
|
||||||
|
return true, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, false
|
||||||
|
}
|
||||||
|
|
||||||
for i := 0; i < listValue.Len(); i++ {
|
for i := 0; i < listValue.Len(); i++ {
|
||||||
if ObjectsAreEqual(listValue.Index(i).Interface(), element) {
|
if ObjectsAreEqual(listValue.Index(i).Interface(), element) {
|
||||||
return true, true
|
return true, true
|
||||||
|
|
@ -527,11 +555,12 @@ func includeElement(list interface{}, element interface{}) (ok, found bool) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Contains asserts that the specified string or list(array, slice...) contains the
|
// Contains asserts that the specified string, list(array, slice...) or map contains the
|
||||||
// specified substring or element.
|
// specified substring or element.
|
||||||
//
|
//
|
||||||
// assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
|
// assert.Contains(t, "Hello World", "World", "But 'Hello World' does contain 'World'")
|
||||||
// assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
|
// assert.Contains(t, ["Hello", "World"], "World", "But ["Hello", "World"] does contain 'World'")
|
||||||
|
// assert.Contains(t, {"Hello": "World"}, "Hello", "But {'Hello': 'World'} does contain 'Hello'")
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
|
@ -548,11 +577,12 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotContains asserts that the specified string or list(array, slice...) does NOT contain the
|
// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the
|
||||||
// specified substring or element.
|
// specified substring or element.
|
||||||
//
|
//
|
||||||
// assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
|
// assert.NotContains(t, "Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
|
||||||
// assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
|
// assert.NotContains(t, ["Hello", "World"], "Earth", "But ['Hello', 'World'] does NOT contain 'Earth'")
|
||||||
|
// assert.NotContains(t, {"Hello": "World"}, "Earth", "But {'Hello': 'World'} does NOT contain 'Earth'")
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
|
@ -736,42 +766,40 @@ func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAn
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// min(|expected|, |actual|) * epsilon
|
func calcRelativeError(expected, actual interface{}) (float64, error) {
|
||||||
func calcEpsilonDelta(expected, actual interface{}, epsilon float64) float64 {
|
|
||||||
af, aok := toFloat(expected)
|
af, aok := toFloat(expected)
|
||||||
|
if !aok {
|
||||||
|
return 0, fmt.Errorf("expected value %q cannot be converted to float", expected)
|
||||||
|
}
|
||||||
|
if af == 0 {
|
||||||
|
return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error")
|
||||||
|
}
|
||||||
bf, bok := toFloat(actual)
|
bf, bok := toFloat(actual)
|
||||||
|
if !bok {
|
||||||
if !aok || !bok {
|
return 0, fmt.Errorf("expected value %q cannot be converted to float", actual)
|
||||||
// invalid input
|
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if af < 0 {
|
return math.Abs(af-bf) / math.Abs(af), nil
|
||||||
af = -af
|
|
||||||
}
|
|
||||||
if bf < 0 {
|
|
||||||
bf = -bf
|
|
||||||
}
|
|
||||||
var delta float64
|
|
||||||
if af < bf {
|
|
||||||
delta = af * epsilon
|
|
||||||
} else {
|
|
||||||
delta = bf * epsilon
|
|
||||||
}
|
|
||||||
return delta
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// InEpsilon asserts that expected and actual have a relative error less than epsilon
|
// InEpsilon asserts that expected and actual have a relative error less than epsilon
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||||
delta := calcEpsilonDelta(expected, actual, epsilon)
|
actualEpsilon, err := calcRelativeError(expected, actual)
|
||||||
|
if err != nil {
|
||||||
|
return Fail(t, err.Error(), msgAndArgs...)
|
||||||
|
}
|
||||||
|
if actualEpsilon > epsilon {
|
||||||
|
return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+
|
||||||
|
" < %#v (actual)", actualEpsilon, epsilon), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
return InDelta(t, expected, actual, delta, msgAndArgs...)
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// InEpsilonSlice is the same as InEpsilon, except it compares two slices.
|
// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices.
|
||||||
func InEpsilonSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
||||||
if expected == nil || actual == nil ||
|
if expected == nil || actual == nil ||
|
||||||
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
reflect.TypeOf(actual).Kind() != reflect.Slice ||
|
||||||
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
reflect.TypeOf(expected).Kind() != reflect.Slice {
|
||||||
|
|
@ -782,7 +810,7 @@ func InEpsilonSlice(t TestingT, expected, actual interface{}, delta float64, msg
|
||||||
expectedSlice := reflect.ValueOf(expected)
|
expectedSlice := reflect.ValueOf(expected)
|
||||||
|
|
||||||
for i := 0; i < actualSlice.Len(); i++ {
|
for i := 0; i < actualSlice.Len(); i++ {
|
||||||
result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta)
|
result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon)
|
||||||
if !result {
|
if !result {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
@ -808,7 +836,7 @@ func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return Fail(t, fmt.Sprintf("No error is expected but got %v", err), msgAndArgs...)
|
return Fail(t, fmt.Sprintf("Received unexpected error %q", err), msgAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error asserts that a function returned an error (i.e. not `nil`).
|
// Error asserts that a function returned an error (i.e. not `nil`).
|
||||||
|
|
@ -842,7 +870,7 @@ func EqualError(t TestingT, theError error, errString string, msgAndArgs ...inte
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
s := "An error with value \"%s\" is expected but got \"%s\". %s"
|
s := "An error with value \"%s\" is expected but got \"%s\". %s"
|
||||||
return Equal(t, theError.Error(), errString,
|
return Equal(t, errString, theError.Error(),
|
||||||
s, errString, theError.Error(), message)
|
s, errString, theError.Error(), message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -893,3 +921,84 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf
|
||||||
return !match
|
return !match
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Zero asserts that i is the zero value for its type and returns the truth.
|
||||||
|
func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
|
||||||
|
return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotZero asserts that i is not the zero value for its type and returns the truth.
|
||||||
|
func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool {
|
||||||
|
if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) {
|
||||||
|
return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONEq asserts that two JSON strings are equivalent.
|
||||||
|
//
|
||||||
|
// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)
|
||||||
|
//
|
||||||
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
|
func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool {
|
||||||
|
var expectedJSONAsInterface, actualJSONAsInterface interface{}
|
||||||
|
|
||||||
|
if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil {
|
||||||
|
return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil {
|
||||||
|
return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) {
|
||||||
|
t := reflect.TypeOf(v)
|
||||||
|
k := t.Kind()
|
||||||
|
|
||||||
|
if k == reflect.Ptr {
|
||||||
|
t = t.Elem()
|
||||||
|
k = t.Kind()
|
||||||
|
}
|
||||||
|
return t, k
|
||||||
|
}
|
||||||
|
|
||||||
|
// diff returns a diff of both values as long as both are of the same type and
|
||||||
|
// are a struct, map, slice or array. Otherwise it returns an empty string.
|
||||||
|
func diff(expected interface{}, actual interface{}) string {
|
||||||
|
if expected == nil || actual == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
et, ek := typeAndKind(expected)
|
||||||
|
at, _ := typeAndKind(actual)
|
||||||
|
|
||||||
|
if et != at {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
spew.Config.SortKeys = true
|
||||||
|
e := spew.Sdump(expected)
|
||||||
|
a := spew.Sdump(actual)
|
||||||
|
|
||||||
|
diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{
|
||||||
|
A: difflib.SplitLines(e),
|
||||||
|
B: difflib.SplitLines(a),
|
||||||
|
FromFile: "Expected",
|
||||||
|
FromDate: "",
|
||||||
|
ToFile: "Actual",
|
||||||
|
ToDate: "",
|
||||||
|
Context: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
return "\n\nDiff:\n" + diff
|
||||||
|
}
|
||||||
|
|
|
||||||
315
Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go
generated
vendored
315
Godeps/_workspace/src/github.com/stretchr/testify/assert/assertions_test.go
generated
vendored
|
|
@ -4,11 +4,80 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
i interface{}
|
||||||
|
zeros = []interface{}{
|
||||||
|
false,
|
||||||
|
byte(0),
|
||||||
|
complex64(0),
|
||||||
|
complex128(0),
|
||||||
|
float32(0),
|
||||||
|
float64(0),
|
||||||
|
int(0),
|
||||||
|
int8(0),
|
||||||
|
int16(0),
|
||||||
|
int32(0),
|
||||||
|
int64(0),
|
||||||
|
rune(0),
|
||||||
|
uint(0),
|
||||||
|
uint8(0),
|
||||||
|
uint16(0),
|
||||||
|
uint32(0),
|
||||||
|
uint64(0),
|
||||||
|
uintptr(0),
|
||||||
|
"",
|
||||||
|
[0]interface{}{},
|
||||||
|
[]interface{}(nil),
|
||||||
|
struct{ x int }{},
|
||||||
|
(*interface{})(nil),
|
||||||
|
(func())(nil),
|
||||||
|
nil,
|
||||||
|
interface{}(nil),
|
||||||
|
map[interface{}]interface{}(nil),
|
||||||
|
(chan interface{})(nil),
|
||||||
|
(<-chan interface{})(nil),
|
||||||
|
(chan<- interface{})(nil),
|
||||||
|
}
|
||||||
|
nonZeros = []interface{}{
|
||||||
|
true,
|
||||||
|
byte(1),
|
||||||
|
complex64(1),
|
||||||
|
complex128(1),
|
||||||
|
float32(1),
|
||||||
|
float64(1),
|
||||||
|
int(1),
|
||||||
|
int8(1),
|
||||||
|
int16(1),
|
||||||
|
int32(1),
|
||||||
|
int64(1),
|
||||||
|
rune(1),
|
||||||
|
uint(1),
|
||||||
|
uint8(1),
|
||||||
|
uint16(1),
|
||||||
|
uint32(1),
|
||||||
|
uint64(1),
|
||||||
|
uintptr(1),
|
||||||
|
"s",
|
||||||
|
[1]interface{}{1},
|
||||||
|
[]interface{}{},
|
||||||
|
struct{ x int }{1},
|
||||||
|
(*interface{})(&i),
|
||||||
|
(func())(func() {}),
|
||||||
|
interface{}(1),
|
||||||
|
map[interface{}]interface{}{},
|
||||||
|
(chan interface{})(make(chan interface{})),
|
||||||
|
(<-chan interface{})(make(chan interface{})),
|
||||||
|
(chan<- interface{})(make(chan interface{})),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// AssertionTesterInterface defines an interface to be used for testing assertion methods
|
// AssertionTesterInterface defines an interface to be used for testing assertion methods
|
||||||
type AssertionTesterInterface interface {
|
type AssertionTesterInterface interface {
|
||||||
TestMethod()
|
TestMethod()
|
||||||
|
|
@ -63,6 +132,12 @@ func TestObjectsAreEqual(t *testing.T) {
|
||||||
if !ObjectsAreEqualValues(uint32(10), int32(10)) {
|
if !ObjectsAreEqualValues(uint32(10), int32(10)) {
|
||||||
t.Error("ObjectsAreEqualValues should return true")
|
t.Error("ObjectsAreEqualValues should return true")
|
||||||
}
|
}
|
||||||
|
if ObjectsAreEqualValues(0, nil) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if ObjectsAreEqualValues(nil, 0) {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,6 +205,9 @@ func TestNotNil(t *testing.T) {
|
||||||
if NotNil(mockT, nil) {
|
if NotNil(mockT, nil) {
|
||||||
t.Error("NotNil should return false: object is nil")
|
t.Error("NotNil should return false: object is nil")
|
||||||
}
|
}
|
||||||
|
if NotNil(mockT, (*struct{})(nil)) {
|
||||||
|
t.Error("NotNil should return false: object is (*struct{})(nil)")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,6 +218,9 @@ func TestNil(t *testing.T) {
|
||||||
if !Nil(mockT, nil) {
|
if !Nil(mockT, nil) {
|
||||||
t.Error("Nil should return true: object is nil")
|
t.Error("Nil should return true: object is nil")
|
||||||
}
|
}
|
||||||
|
if !Nil(mockT, (*struct{})(nil)) {
|
||||||
|
t.Error("Nil should return true: object is (*struct{})(nil)")
|
||||||
|
}
|
||||||
if Nil(mockT, new(AssertionTesterConformingObject)) {
|
if Nil(mockT, new(AssertionTesterConformingObject)) {
|
||||||
t.Error("Nil should return false: object is not nil")
|
t.Error("Nil should return false: object is not nil")
|
||||||
}
|
}
|
||||||
|
|
@ -256,6 +337,7 @@ func TestContains(t *testing.T) {
|
||||||
{"g", "h"},
|
{"g", "h"},
|
||||||
{"j", "k"},
|
{"j", "k"},
|
||||||
}
|
}
|
||||||
|
simpleMap := map[interface{}]interface{}{"Foo": "Bar"}
|
||||||
|
|
||||||
if !Contains(mockT, "Hello World", "Hello") {
|
if !Contains(mockT, "Hello World", "Hello") {
|
||||||
t.Error("Contains should return true: \"Hello World\" contains \"Hello\"")
|
t.Error("Contains should return true: \"Hello World\" contains \"Hello\"")
|
||||||
|
|
@ -276,12 +358,22 @@ func TestContains(t *testing.T) {
|
||||||
if Contains(mockT, complexList, &A{"g", "e"}) {
|
if Contains(mockT, complexList, &A{"g", "e"}) {
|
||||||
t.Error("Contains should return false: complexList contains {\"g\", \"e\"}")
|
t.Error("Contains should return false: complexList contains {\"g\", \"e\"}")
|
||||||
}
|
}
|
||||||
|
if Contains(mockT, complexList, &A{"g", "e"}) {
|
||||||
|
t.Error("Contains should return false: complexList contains {\"g\", \"e\"}")
|
||||||
|
}
|
||||||
|
if !Contains(mockT, simpleMap, "Foo") {
|
||||||
|
t.Error("Contains should return true: \"{\"Foo\": \"Bar\"}\" contains \"Foo\"")
|
||||||
|
}
|
||||||
|
if Contains(mockT, simpleMap, "Bar") {
|
||||||
|
t.Error("Contains should return false: \"{\"Foo\": \"Bar\"}\" does not contains \"Bar\"")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotContains(t *testing.T) {
|
func TestNotContains(t *testing.T) {
|
||||||
|
|
||||||
mockT := new(testing.T)
|
mockT := new(testing.T)
|
||||||
list := []string{"Foo", "Bar"}
|
list := []string{"Foo", "Bar"}
|
||||||
|
simpleMap := map[interface{}]interface{}{"Foo": "Bar"}
|
||||||
|
|
||||||
if !NotContains(mockT, "Hello World", "Hello!") {
|
if !NotContains(mockT, "Hello World", "Hello!") {
|
||||||
t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"")
|
t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"")
|
||||||
|
|
@ -296,13 +388,19 @@ func TestNotContains(t *testing.T) {
|
||||||
if NotContains(mockT, list, "Foo") {
|
if NotContains(mockT, list, "Foo") {
|
||||||
t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"")
|
t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"")
|
||||||
}
|
}
|
||||||
|
if NotContains(mockT, simpleMap, "Foo") {
|
||||||
|
t.Error("Contains should return true: \"{\"Foo\": \"Bar\"}\" contains \"Foo\"")
|
||||||
|
}
|
||||||
|
if !NotContains(mockT, simpleMap, "Bar") {
|
||||||
|
t.Error("Contains should return false: \"{\"Foo\": \"Bar\"}\" does not contains \"Bar\"")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_includeElement(t *testing.T) {
|
func Test_includeElement(t *testing.T) {
|
||||||
|
|
||||||
list1 := []string{"Foo", "Bar"}
|
list1 := []string{"Foo", "Bar"}
|
||||||
list2 := []int{1, 2}
|
list2 := []int{1, 2}
|
||||||
|
simpleMap := map[interface{}]interface{}{"Foo": "Bar"}
|
||||||
|
|
||||||
ok, found := includeElement("Hello World", "World")
|
ok, found := includeElement("Hello World", "World")
|
||||||
True(t, ok)
|
True(t, ok)
|
||||||
|
|
@ -336,10 +434,17 @@ func Test_includeElement(t *testing.T) {
|
||||||
True(t, ok)
|
True(t, ok)
|
||||||
False(t, found)
|
False(t, found)
|
||||||
|
|
||||||
|
ok, found = includeElement(simpleMap, "Foo")
|
||||||
|
True(t, ok)
|
||||||
|
True(t, found)
|
||||||
|
|
||||||
|
ok, found = includeElement(simpleMap, "Bar")
|
||||||
|
True(t, ok)
|
||||||
|
False(t, found)
|
||||||
|
|
||||||
ok, found = includeElement(1433, "1")
|
ok, found = includeElement(1433, "1")
|
||||||
False(t, ok)
|
False(t, ok)
|
||||||
False(t, found)
|
False(t, found)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCondition(t *testing.T) {
|
func TestCondition(t *testing.T) {
|
||||||
|
|
@ -466,6 +571,7 @@ func Test_isEmpty(t *testing.T) {
|
||||||
True(t, isEmpty(false))
|
True(t, isEmpty(false))
|
||||||
True(t, isEmpty(map[string]string{}))
|
True(t, isEmpty(map[string]string{}))
|
||||||
True(t, isEmpty(new(time.Time)))
|
True(t, isEmpty(new(time.Time)))
|
||||||
|
True(t, isEmpty(time.Time{}))
|
||||||
True(t, isEmpty(make(chan struct{})))
|
True(t, isEmpty(make(chan struct{})))
|
||||||
False(t, isEmpty("something"))
|
False(t, isEmpty("something"))
|
||||||
False(t, isEmpty(errors.New("something")))
|
False(t, isEmpty(errors.New("something")))
|
||||||
|
|
@ -482,6 +588,10 @@ func TestEmpty(t *testing.T) {
|
||||||
mockT := new(testing.T)
|
mockT := new(testing.T)
|
||||||
chWithValue := make(chan struct{}, 1)
|
chWithValue := make(chan struct{}, 1)
|
||||||
chWithValue <- struct{}{}
|
chWithValue <- struct{}{}
|
||||||
|
var tiP *time.Time
|
||||||
|
var tiNP time.Time
|
||||||
|
var s *string
|
||||||
|
var f *os.File
|
||||||
|
|
||||||
True(t, Empty(mockT, ""), "Empty string is empty")
|
True(t, Empty(mockT, ""), "Empty string is empty")
|
||||||
True(t, Empty(mockT, nil), "Nil is empty")
|
True(t, Empty(mockT, nil), "Nil is empty")
|
||||||
|
|
@ -489,6 +599,10 @@ func TestEmpty(t *testing.T) {
|
||||||
True(t, Empty(mockT, 0), "Zero int value is empty")
|
True(t, Empty(mockT, 0), "Zero int value is empty")
|
||||||
True(t, Empty(mockT, false), "False value is empty")
|
True(t, Empty(mockT, false), "False value is empty")
|
||||||
True(t, Empty(mockT, make(chan struct{})), "Channel without values is empty")
|
True(t, Empty(mockT, make(chan struct{})), "Channel without values is empty")
|
||||||
|
True(t, Empty(mockT, s), "Nil string pointer is empty")
|
||||||
|
True(t, Empty(mockT, f), "Nil os.File pointer is empty")
|
||||||
|
True(t, Empty(mockT, tiP), "Nil time.Time pointer is empty")
|
||||||
|
True(t, Empty(mockT, tiNP), "time.Time is empty")
|
||||||
|
|
||||||
False(t, Empty(mockT, "something"), "Non Empty string is not empty")
|
False(t, Empty(mockT, "something"), "Non Empty string is not empty")
|
||||||
False(t, Empty(mockT, errors.New("something")), "Non nil object is not empty")
|
False(t, Empty(mockT, errors.New("something")), "Non nil object is not empty")
|
||||||
|
|
@ -716,10 +830,11 @@ func TestInEpsilon(t *testing.T) {
|
||||||
{-2.2, -2.1, 0.1},
|
{-2.2, -2.1, 0.1},
|
||||||
{uint64(100), uint8(101), 0.01},
|
{uint64(100), uint8(101), 0.01},
|
||||||
{0.1, -0.1, 2},
|
{0.1, -0.1, 2},
|
||||||
|
{0.1, 0, 2},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
True(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon))
|
True(t, InEpsilon(t, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon), "test: %q", tc)
|
||||||
}
|
}
|
||||||
|
|
||||||
cases = []struct {
|
cases = []struct {
|
||||||
|
|
@ -733,6 +848,7 @@ func TestInEpsilon(t *testing.T) {
|
||||||
{2.1, -2.2, 1},
|
{2.1, -2.2, 1},
|
||||||
{2.1, "bla-bla", 0},
|
{2.1, "bla-bla", 0},
|
||||||
{0.1, -0.1, 1.99},
|
{0.1, -0.1, 1.99},
|
||||||
|
{0, 0.1, 2}, // expected must be different to zero
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
|
|
@ -811,3 +927,196 @@ func TestCallerInfoWithAutogeneratedFunctions(t *testing.T) {
|
||||||
testAutogeneratedFunction()
|
testAutogeneratedFunction()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestZero(t *testing.T) {
|
||||||
|
mockT := new(testing.T)
|
||||||
|
|
||||||
|
for _, test := range zeros {
|
||||||
|
True(t, Zero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test)))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range nonZeros {
|
||||||
|
False(t, Zero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotZero(t *testing.T) {
|
||||||
|
mockT := new(testing.T)
|
||||||
|
|
||||||
|
for _, test := range zeros {
|
||||||
|
False(t, NotZero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test)))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range nonZeros {
|
||||||
|
True(t, NotZero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEq_EqualSONString(t *testing.T) {
|
||||||
|
mockT := new(testing.T)
|
||||||
|
True(t, JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEq_EquivalentButNotEqual(t *testing.T) {
|
||||||
|
mockT := new(testing.T)
|
||||||
|
True(t, JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEq_HashOfArraysAndHashes(t *testing.T) {
|
||||||
|
mockT := new(testing.T)
|
||||||
|
True(t, JSONEq(mockT, "{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}",
|
||||||
|
"{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEq_Array(t *testing.T) {
|
||||||
|
mockT := new(testing.T)
|
||||||
|
True(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) {
|
||||||
|
mockT := new(testing.T)
|
||||||
|
False(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEq_HashesNotEquivalent(t *testing.T) {
|
||||||
|
mockT := new(testing.T)
|
||||||
|
False(t, JSONEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEq_ActualIsNotJSON(t *testing.T) {
|
||||||
|
mockT := new(testing.T)
|
||||||
|
False(t, JSONEq(mockT, `{"foo": "bar"}`, "Not JSON"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEq_ExpectedIsNotJSON(t *testing.T) {
|
||||||
|
mockT := new(testing.T)
|
||||||
|
False(t, JSONEq(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) {
|
||||||
|
mockT := new(testing.T)
|
||||||
|
False(t, JSONEq(mockT, "Not JSON", "Not JSON"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) {
|
||||||
|
mockT := new(testing.T)
|
||||||
|
False(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiff(t *testing.T) {
|
||||||
|
expected := `
|
||||||
|
|
||||||
|
Diff:
|
||||||
|
--- Expected
|
||||||
|
+++ Actual
|
||||||
|
@@ -1,3 +1,3 @@
|
||||||
|
(struct { foo string }) {
|
||||||
|
- foo: (string) (len=5) "hello"
|
||||||
|
+ foo: (string) (len=3) "bar"
|
||||||
|
}
|
||||||
|
`
|
||||||
|
actual := diff(
|
||||||
|
struct{ foo string }{"hello"},
|
||||||
|
struct{ foo string }{"bar"},
|
||||||
|
)
|
||||||
|
Equal(t, expected, actual)
|
||||||
|
|
||||||
|
expected = `
|
||||||
|
|
||||||
|
Diff:
|
||||||
|
--- Expected
|
||||||
|
+++ Actual
|
||||||
|
@@ -2,5 +2,5 @@
|
||||||
|
(int) 1,
|
||||||
|
- (int) 2,
|
||||||
|
(int) 3,
|
||||||
|
- (int) 4
|
||||||
|
+ (int) 5,
|
||||||
|
+ (int) 7
|
||||||
|
}
|
||||||
|
`
|
||||||
|
actual = diff(
|
||||||
|
[]int{1, 2, 3, 4},
|
||||||
|
[]int{1, 3, 5, 7},
|
||||||
|
)
|
||||||
|
Equal(t, expected, actual)
|
||||||
|
|
||||||
|
expected = `
|
||||||
|
|
||||||
|
Diff:
|
||||||
|
--- Expected
|
||||||
|
+++ Actual
|
||||||
|
@@ -2,4 +2,4 @@
|
||||||
|
(int) 1,
|
||||||
|
- (int) 2,
|
||||||
|
- (int) 3
|
||||||
|
+ (int) 3,
|
||||||
|
+ (int) 5
|
||||||
|
}
|
||||||
|
`
|
||||||
|
actual = diff(
|
||||||
|
[]int{1, 2, 3, 4}[0:3],
|
||||||
|
[]int{1, 3, 5, 7}[0:3],
|
||||||
|
)
|
||||||
|
Equal(t, expected, actual)
|
||||||
|
|
||||||
|
expected = `
|
||||||
|
|
||||||
|
Diff:
|
||||||
|
--- Expected
|
||||||
|
+++ Actual
|
||||||
|
@@ -1,6 +1,6 @@
|
||||||
|
(map[string]int) (len=4) {
|
||||||
|
- (string) (len=4) "four": (int) 4,
|
||||||
|
+ (string) (len=4) "five": (int) 5,
|
||||||
|
(string) (len=3) "one": (int) 1,
|
||||||
|
- (string) (len=5) "three": (int) 3,
|
||||||
|
- (string) (len=3) "two": (int) 2
|
||||||
|
+ (string) (len=5) "seven": (int) 7,
|
||||||
|
+ (string) (len=5) "three": (int) 3
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
actual = diff(
|
||||||
|
map[string]int{"one": 1, "two": 2, "three": 3, "four": 4},
|
||||||
|
map[string]int{"one": 1, "three": 3, "five": 5, "seven": 7},
|
||||||
|
)
|
||||||
|
Equal(t, expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiffEmptyCases(t *testing.T) {
|
||||||
|
Equal(t, "", diff(nil, nil))
|
||||||
|
Equal(t, "", diff(struct{ foo string }{}, nil))
|
||||||
|
Equal(t, "", diff(nil, struct{ foo string }{}))
|
||||||
|
Equal(t, "", diff(1, 2))
|
||||||
|
Equal(t, "", diff(1, 2))
|
||||||
|
Equal(t, "", diff([]int{1}, []bool{true}))
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockTestingT struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockTestingT) Errorf(format string, args ...interface{}) {}
|
||||||
|
|
||||||
|
func TestFailNowWithPlainTestingT(t *testing.T) {
|
||||||
|
mockT := &mockTestingT{}
|
||||||
|
|
||||||
|
Panics(t, func() {
|
||||||
|
FailNow(mockT, "failed")
|
||||||
|
}, "should panic since mockT is missing FailNow()")
|
||||||
|
}
|
||||||
|
|
||||||
|
type mockFailNowTestingT struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mockFailNowTestingT) Errorf(format string, args ...interface{}) {}
|
||||||
|
|
||||||
|
func (m *mockFailNowTestingT) FailNow() {}
|
||||||
|
|
||||||
|
func TestFailNowWithFullTestingT(t *testing.T) {
|
||||||
|
mockT := &mockFailNowTestingT{}
|
||||||
|
|
||||||
|
NotPanics(t, func() {
|
||||||
|
FailNow(mockT, "failed")
|
||||||
|
}, "should call mockT.FailNow() rather than panicking")
|
||||||
|
}
|
||||||
|
|
|
||||||
111
Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go
generated
vendored
111
Godeps/_workspace/src/github.com/stretchr/testify/assert/doc.go
generated
vendored
|
|
@ -17,7 +17,7 @@
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// if you assert many times, use the below:
|
// if you assert many times, use the format below:
|
||||||
//
|
//
|
||||||
// import (
|
// import (
|
||||||
// "testing"
|
// "testing"
|
||||||
|
|
@ -42,113 +42,4 @@
|
||||||
//
|
//
|
||||||
// Every assertion function also takes an optional string message as the final argument,
|
// Every assertion function also takes an optional string message as the final argument,
|
||||||
// allowing custom error messages to be appended to the message the assertion method outputs.
|
// allowing custom error messages to be appended to the message the assertion method outputs.
|
||||||
//
|
|
||||||
// Here is an overview of the assert functions:
|
|
||||||
//
|
|
||||||
// assert.Equal(t, expected, actual [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.EqualValues(t, expected, actual [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.NotEqual(t, notExpected, actual [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.True(t, actualBool [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.False(t, actualBool [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Nil(t, actualObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.NotNil(t, actualObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Empty(t, actualObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.NotEmpty(t, actualObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Len(t, actualObject, expectedLength, [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Error(t, errorObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.NoError(t, errorObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.EqualError(t, theError, errString [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Implements(t, (*MyInterface)(nil), new(MyObject) [,message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.IsType(t, expectedObject, actualObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Contains(t, stringOrSlice, substringOrElement [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.NotContains(t, stringOrSlice, substringOrElement [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Panics(t, func(){
|
|
||||||
//
|
|
||||||
// // call code that should panic
|
|
||||||
//
|
|
||||||
// } [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.NotPanics(t, func(){
|
|
||||||
//
|
|
||||||
// // call code that should not panic
|
|
||||||
//
|
|
||||||
// } [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.WithinDuration(t, timeA, timeB, deltaTime, [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.InDelta(t, numA, numB, delta, [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.InEpsilon(t, numA, numB, epsilon, [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert package contains Assertions object. it has assertion methods.
|
|
||||||
//
|
|
||||||
// Here is an overview of the assert functions:
|
|
||||||
// assert.Equal(expected, actual [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.EqualValues(expected, actual [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.NotEqual(notExpected, actual [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.True(actualBool [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.False(actualBool [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Nil(actualObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.NotNil(actualObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Empty(actualObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.NotEmpty(actualObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Len(actualObject, expectedLength, [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Error(errorObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.NoError(errorObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.EqualError(theError, errString [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Implements((*MyInterface)(nil), new(MyObject) [,message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.IsType(expectedObject, actualObject [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Contains(stringOrSlice, substringOrElement [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.NotContains(stringOrSlice, substringOrElement [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.Panics(func(){
|
|
||||||
//
|
|
||||||
// // call code that should panic
|
|
||||||
//
|
|
||||||
// } [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.NotPanics(func(){
|
|
||||||
//
|
|
||||||
// // call code that should not panic
|
|
||||||
//
|
|
||||||
// } [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.WithinDuration(timeA, timeB, deltaTime, [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.InDelta(numA, numB, delta, [, message [, format-args]])
|
|
||||||
//
|
|
||||||
// assert.InEpsilon(numA, numB, epsilon, [, message [, format-args]])
|
|
||||||
package assert
|
package assert
|
||||||
|
|
|
||||||
251
Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go
generated
vendored
251
Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions.go
generated
vendored
|
|
@ -1,7 +1,5 @@
|
||||||
package assert
|
package assert
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
// Assertions provides assertion methods around the
|
// Assertions provides assertion methods around the
|
||||||
// TestingT interface.
|
// TestingT interface.
|
||||||
type Assertions struct {
|
type Assertions struct {
|
||||||
|
|
@ -15,251 +13,4 @@ func New(t TestingT) *Assertions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fail reports a failure through
|
//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl
|
||||||
func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool {
|
|
||||||
return Fail(a.t, failureMessage, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements asserts that an object is implemented by the specified interface.
|
|
||||||
//
|
|
||||||
// assert.Implements((*MyInterface)(nil), new(MyObject), "MyObject")
|
|
||||||
func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return Implements(a.t, interfaceObject, object, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsType asserts that the specified objects are of the same type.
|
|
||||||
func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return IsType(a.t, expectedType, object, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Equal asserts that two objects are equal.
|
|
||||||
//
|
|
||||||
// assert.Equal(123, 123, "123 and 123 should be equal")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) Equal(expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return Equal(a.t, expected, actual, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EqualValues asserts that two objects are equal or convertable to the same types
|
|
||||||
// and equal.
|
|
||||||
//
|
|
||||||
// assert.EqualValues(uint32(123), int32(123), "123 and 123 should be equal")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) EqualValues(expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return EqualValues(a.t, expected, actual, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exactly asserts that two objects are equal is value and type.
|
|
||||||
//
|
|
||||||
// assert.Exactly(int32(123), int64(123), "123 and 123 should NOT be equal")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) Exactly(expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return Exactly(a.t, expected, actual, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotNil asserts that the specified object is not nil.
|
|
||||||
//
|
|
||||||
// assert.NotNil(err, "err should be something")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return NotNil(a.t, object, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nil asserts that the specified object is nil.
|
|
||||||
//
|
|
||||||
// assert.Nil(err, "err should be nothing")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return Nil(a.t, object, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or a
|
|
||||||
// slice with len == 0.
|
|
||||||
//
|
|
||||||
// assert.Empty(obj)
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return Empty(a.t, object, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or a
|
|
||||||
// slice with len == 0.
|
|
||||||
//
|
|
||||||
// if assert.NotEmpty(obj) {
|
|
||||||
// assert.Equal("two", obj[1])
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return NotEmpty(a.t, object, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len asserts that the specified object has specific length.
|
|
||||||
// Len also fails if the object has a type that len() not accept.
|
|
||||||
//
|
|
||||||
// assert.Len(mySlice, 3, "The size of slice is not 3")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool {
|
|
||||||
return Len(a.t, object, length, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// True asserts that the specified value is true.
|
|
||||||
//
|
|
||||||
// assert.True(myBool, "myBool should be true")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool {
|
|
||||||
return True(a.t, value, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// False asserts that the specified value is true.
|
|
||||||
//
|
|
||||||
// assert.False(myBool, "myBool should be false")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool {
|
|
||||||
return False(a.t, value, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotEqual asserts that the specified values are NOT equal.
|
|
||||||
//
|
|
||||||
// assert.NotEqual(obj1, obj2, "two objects shouldn't be equal")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) NotEqual(expected, actual interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return NotEqual(a.t, expected, actual, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contains asserts that the specified string contains the specified substring.
|
|
||||||
//
|
|
||||||
// assert.Contains("Hello World", "World", "But 'Hello World' does contain 'World'")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) Contains(s, contains interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return Contains(a.t, s, contains, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotContains asserts that the specified string does NOT contain the specified substring.
|
|
||||||
//
|
|
||||||
// assert.NotContains("Hello World", "Earth", "But 'Hello World' does NOT contain 'Earth'")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) NotContains(s, contains interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return NotContains(a.t, s, contains, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Condition uses a Comparison to assert a complex condition.
|
|
||||||
func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool {
|
|
||||||
return Condition(a.t, comp, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panics asserts that the code inside the specified PanicTestFunc panics.
|
|
||||||
//
|
|
||||||
// assert.Panics(func(){
|
|
||||||
// GoCrazy()
|
|
||||||
// }, "Calling GoCrazy() should panic")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
|
||||||
return Panics(a.t, f, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic.
|
|
||||||
//
|
|
||||||
// assert.NotPanics(func(){
|
|
||||||
// RemainCalm()
|
|
||||||
// }, "Calling RemainCalm() should NOT panic")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool {
|
|
||||||
return NotPanics(a.t, f, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithinDuration asserts that the two times are within duration delta of each other.
|
|
||||||
//
|
|
||||||
// assert.WithinDuration(time.Now(), time.Now(), 10*time.Second, "The difference should not be more than 10s")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) WithinDuration(expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool {
|
|
||||||
return WithinDuration(a.t, expected, actual, delta, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InDelta asserts that the two numerals are within delta of each other.
|
|
||||||
//
|
|
||||||
// assert.InDelta(t, math.Pi, (22 / 7.0), 0.01)
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) InDelta(expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool {
|
|
||||||
return InDelta(a.t, expected, actual, delta, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// InEpsilon asserts that expected and actual have a relative error less than epsilon
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) InEpsilon(expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool {
|
|
||||||
return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NoError asserts that a function returned no error (i.e. `nil`).
|
|
||||||
//
|
|
||||||
// actualObj, err := SomeFunction()
|
|
||||||
// if assert.NoError(err) {
|
|
||||||
// assert.Equal(actualObj, expectedObj)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) NoError(theError error, msgAndArgs ...interface{}) bool {
|
|
||||||
return NoError(a.t, theError, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error asserts that a function returned an error (i.e. not `nil`).
|
|
||||||
//
|
|
||||||
// actualObj, err := SomeFunction()
|
|
||||||
// if assert.Error(err, "An error was expected") {
|
|
||||||
// assert.Equal(err, expectedError)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) Error(theError error, msgAndArgs ...interface{}) bool {
|
|
||||||
return Error(a.t, theError, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EqualError asserts that a function returned an error (i.e. not `nil`)
|
|
||||||
// and that it is equal to the provided error.
|
|
||||||
//
|
|
||||||
// actualObj, err := SomeFunction()
|
|
||||||
// if assert.Error(err, "An error was expected") {
|
|
||||||
// assert.Equal(err, expectedError)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool {
|
|
||||||
return EqualError(a.t, theError, errString, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Regexp asserts that a specified regexp matches a string.
|
|
||||||
//
|
|
||||||
// assert.Regexp(t, regexp.MustCompile("start"), "it's starting")
|
|
||||||
// assert.Regexp(t, "start...$", "it's not starting")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return Regexp(a.t, rx, str, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotRegexp asserts that a specified regexp does not match a string.
|
|
||||||
//
|
|
||||||
// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting")
|
|
||||||
// assert.NotRegexp(t, "^start", "it's not starting")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool {
|
|
||||||
return NotRegexp(a.t, rx, str, msgAndArgs...)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
100
Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go
generated
vendored
100
Godeps/_workspace/src/github.com/stretchr/testify/assert/forward_assertions_test.go
generated
vendored
|
|
@ -509,3 +509,103 @@ func TestRegexpWrapper(t *testing.T) {
|
||||||
True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str))
|
True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestZeroWrapper(t *testing.T) {
|
||||||
|
assert := New(t)
|
||||||
|
mockAssert := New(new(testing.T))
|
||||||
|
|
||||||
|
for _, test := range zeros {
|
||||||
|
assert.True(mockAssert.Zero(test), "Zero should return true for %v", test)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range nonZeros {
|
||||||
|
assert.False(mockAssert.Zero(test), "Zero should return false for %v", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotZeroWrapper(t *testing.T) {
|
||||||
|
assert := New(t)
|
||||||
|
mockAssert := New(new(testing.T))
|
||||||
|
|
||||||
|
for _, test := range zeros {
|
||||||
|
assert.False(mockAssert.NotZero(test), "Zero should return true for %v", test)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range nonZeros {
|
||||||
|
assert.True(mockAssert.NotZero(test), "Zero should return false for %v", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEqWrapper_EqualSONString(t *testing.T) {
|
||||||
|
assert := New(new(testing.T))
|
||||||
|
if !assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) {
|
||||||
|
t.Error("JSONEq should return true")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEqWrapper_EquivalentButNotEqual(t *testing.T) {
|
||||||
|
assert := New(new(testing.T))
|
||||||
|
if !assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) {
|
||||||
|
t.Error("JSONEq should return true")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEqWrapper_HashOfArraysAndHashes(t *testing.T) {
|
||||||
|
assert := New(new(testing.T))
|
||||||
|
if !assert.JSONEq("{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}",
|
||||||
|
"{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}") {
|
||||||
|
t.Error("JSONEq should return true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEqWrapper_Array(t *testing.T) {
|
||||||
|
assert := New(new(testing.T))
|
||||||
|
if !assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) {
|
||||||
|
t.Error("JSONEq should return true")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEqWrapper_HashAndArrayNotEquivalent(t *testing.T) {
|
||||||
|
assert := New(new(testing.T))
|
||||||
|
if assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) {
|
||||||
|
t.Error("JSONEq should return false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEqWrapper_HashesNotEquivalent(t *testing.T) {
|
||||||
|
assert := New(new(testing.T))
|
||||||
|
if assert.JSONEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) {
|
||||||
|
t.Error("JSONEq should return false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEqWrapper_ActualIsNotJSON(t *testing.T) {
|
||||||
|
assert := New(new(testing.T))
|
||||||
|
if assert.JSONEq(`{"foo": "bar"}`, "Not JSON") {
|
||||||
|
t.Error("JSONEq should return false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEqWrapper_ExpectedIsNotJSON(t *testing.T) {
|
||||||
|
assert := New(new(testing.T))
|
||||||
|
if assert.JSONEq("Not JSON", `{"foo": "bar", "hello": "world"}`) {
|
||||||
|
t.Error("JSONEq should return false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEqWrapper_ExpectedAndActualNotJSON(t *testing.T) {
|
||||||
|
assert := New(new(testing.T))
|
||||||
|
if assert.JSONEq("Not JSON", "Not JSON") {
|
||||||
|
t.Error("JSONEq should return false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) {
|
||||||
|
assert := New(new(testing.T))
|
||||||
|
if assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) {
|
||||||
|
t.Error("JSONEq should return false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
79
Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go
generated
vendored
79
Godeps/_workspace/src/github.com/stretchr/testify/assert/http_assertions.go
generated
vendored
|
|
@ -10,9 +10,9 @@ import (
|
||||||
|
|
||||||
// httpCode is a helper that returns HTTP code of the response. It returns -1
|
// httpCode is a helper that returns HTTP code of the response. It returns -1
|
||||||
// if building a new request fails.
|
// if building a new request fails.
|
||||||
func httpCode(handler http.HandlerFunc, mode, url string, values url.Values) int {
|
func httpCode(handler http.HandlerFunc, method, url string, values url.Values) int {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
req, err := http.NewRequest(mode, url+"?"+values.Encode(), nil)
|
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
@ -25,8 +25,8 @@ func httpCode(handler http.HandlerFunc, mode, url string, values url.Values) int
|
||||||
// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
|
// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil)
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func HTTPSuccess(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool {
|
func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
|
||||||
code := httpCode(handler, mode, url, values)
|
code := httpCode(handler, method, url, values)
|
||||||
if code == -1 {
|
if code == -1 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -38,8 +38,8 @@ func HTTPSuccess(t TestingT, handler http.HandlerFunc, mode, url string, values
|
||||||
// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func HTTPRedirect(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool {
|
func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
|
||||||
code := httpCode(handler, mode, url, values)
|
code := httpCode(handler, method, url, values)
|
||||||
if code == -1 {
|
if code == -1 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -51,8 +51,8 @@ func HTTPRedirect(t TestingT, handler http.HandlerFunc, mode, url string, values
|
||||||
// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func HTTPError(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values) bool {
|
func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values) bool {
|
||||||
code := httpCode(handler, mode, url, values)
|
code := httpCode(handler, method, url, values)
|
||||||
if code == -1 {
|
if code == -1 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -61,9 +61,9 @@ func HTTPError(t TestingT, handler http.HandlerFunc, mode, url string, values ur
|
||||||
|
|
||||||
// HTTPBody is a helper that returns HTTP body of the response. It returns
|
// HTTPBody is a helper that returns HTTP body of the response. It returns
|
||||||
// empty string if building a new request fails.
|
// empty string if building a new request fails.
|
||||||
func HTTPBody(handler http.HandlerFunc, mode, url string, values url.Values) string {
|
func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string {
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
req, err := http.NewRequest(mode, url+"?"+values.Encode(), nil)
|
req, err := http.NewRequest(method, url+"?"+values.Encode(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
@ -77,8 +77,8 @@ func HTTPBody(handler http.HandlerFunc, mode, url string, values url.Values) str
|
||||||
// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool {
|
func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
|
||||||
body := HTTPBody(handler, mode, url, values)
|
body := HTTPBody(handler, method, url, values)
|
||||||
|
|
||||||
contains := strings.Contains(body, fmt.Sprint(str))
|
contains := strings.Contains(body, fmt.Sprint(str))
|
||||||
if !contains {
|
if !contains {
|
||||||
|
|
@ -94,8 +94,8 @@ func HTTPBodyContains(t TestingT, handler http.HandlerFunc, mode, url string, va
|
||||||
// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
||||||
//
|
//
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
// Returns whether the assertion was successful (true) or not (false).
|
||||||
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool {
|
func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}) bool {
|
||||||
body := HTTPBody(handler, mode, url, values)
|
body := HTTPBody(handler, method, url, values)
|
||||||
|
|
||||||
contains := strings.Contains(body, fmt.Sprint(str))
|
contains := strings.Contains(body, fmt.Sprint(str))
|
||||||
if contains {
|
if contains {
|
||||||
|
|
@ -104,54 +104,3 @@ func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, mode, url string,
|
||||||
|
|
||||||
return !contains
|
return !contains
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Assertions Wrappers
|
|
||||||
//
|
|
||||||
|
|
||||||
// HTTPSuccess asserts that a specified handler returns a success status code.
|
|
||||||
//
|
|
||||||
// assert.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil)
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, mode, url string, values url.Values) bool {
|
|
||||||
return HTTPSuccess(a.t, handler, mode, url, values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPRedirect asserts that a specified handler returns a redirect status code.
|
|
||||||
//
|
|
||||||
// assert.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, mode, url string, values url.Values) bool {
|
|
||||||
return HTTPRedirect(a.t, handler, mode, url, values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPError asserts that a specified handler returns an error status code.
|
|
||||||
//
|
|
||||||
// assert.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}}
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) HTTPError(handler http.HandlerFunc, mode, url string, values url.Values) bool {
|
|
||||||
return HTTPError(a.t, handler, mode, url, values)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPBodyContains asserts that a specified handler returns a
|
|
||||||
// body that contains a string.
|
|
||||||
//
|
|
||||||
// assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool {
|
|
||||||
return HTTPBodyContains(a.t, handler, mode, url, values, str)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTPBodyNotContains asserts that a specified handler returns a
|
|
||||||
// body that does not contain a string.
|
|
||||||
//
|
|
||||||
// assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky")
|
|
||||||
//
|
|
||||||
// Returns whether the assertion was successful (true) or not (false).
|
|
||||||
func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, mode, url string, values url.Values, str interface{}) bool {
|
|
||||||
return HTTPBodyNotContains(a.t, handler, mode, url, values, str)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
3
Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go
generated
vendored
3
Godeps/_workspace/src/github.com/stretchr/testify/mock/doc.go
generated
vendored
|
|
@ -1,4 +1,5 @@
|
||||||
// Provides a system by which it is possible to mock your objects and verify calls are happening as expected.
|
// Package mock provides a system by which it is possible to mock your objects
|
||||||
|
// and verify calls are happening as expected.
|
||||||
//
|
//
|
||||||
// Example Usage
|
// Example Usage
|
||||||
//
|
//
|
||||||
|
|
|
||||||
337
Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go
generated
vendored
337
Godeps/_workspace/src/github.com/stretchr/testify/mock/mock.go
generated
vendored
|
|
@ -3,6 +3,7 @@ package mock
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -16,6 +17,7 @@ import (
|
||||||
type TestingT interface {
|
type TestingT interface {
|
||||||
Logf(format string, args ...interface{})
|
Logf(format string, args ...interface{})
|
||||||
Errorf(format string, args ...interface{})
|
Errorf(format string, args ...interface{})
|
||||||
|
FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -25,6 +27,7 @@ type TestingT interface {
|
||||||
// Call represents a method call and is used for setting expectations,
|
// Call represents a method call and is used for setting expectations,
|
||||||
// as well as recording activity.
|
// as well as recording activity.
|
||||||
type Call struct {
|
type Call struct {
|
||||||
|
Parent *Mock
|
||||||
|
|
||||||
// The name of the method that was or will be called.
|
// The name of the method that was or will be called.
|
||||||
Method string
|
Method string
|
||||||
|
|
@ -47,24 +50,116 @@ type Call struct {
|
||||||
// Holds a handler used to manipulate arguments content that are passed by
|
// Holds a handler used to manipulate arguments content that are passed by
|
||||||
// reference. It's useful when mocking methods such as unmarshalers or
|
// reference. It's useful when mocking methods such as unmarshalers or
|
||||||
// decoders.
|
// decoders.
|
||||||
Run func(Arguments)
|
RunFn func(Arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCall(parent *Mock, methodName string, methodArguments ...interface{}) *Call {
|
||||||
|
return &Call{
|
||||||
|
Parent: parent,
|
||||||
|
Method: methodName,
|
||||||
|
Arguments: methodArguments,
|
||||||
|
ReturnArguments: make([]interface{}, 0),
|
||||||
|
Repeatability: 0,
|
||||||
|
WaitFor: nil,
|
||||||
|
RunFn: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Call) lock() {
|
||||||
|
c.Parent.mutex.Lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Call) unlock() {
|
||||||
|
c.Parent.mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return specifies the return arguments for the expectation.
|
||||||
|
//
|
||||||
|
// Mock.On("DoSomething").Return(errors.New("failed"))
|
||||||
|
func (c *Call) Return(returnArguments ...interface{}) *Call {
|
||||||
|
c.lock()
|
||||||
|
defer c.unlock()
|
||||||
|
|
||||||
|
c.ReturnArguments = returnArguments
|
||||||
|
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once indicates that that the mock should only return the value once.
|
||||||
|
//
|
||||||
|
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once()
|
||||||
|
func (c *Call) Once() *Call {
|
||||||
|
return c.Times(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Twice indicates that that the mock should only return the value twice.
|
||||||
|
//
|
||||||
|
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice()
|
||||||
|
func (c *Call) Twice() *Call {
|
||||||
|
return c.Times(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Times indicates that that the mock should only return the indicated number
|
||||||
|
// of times.
|
||||||
|
//
|
||||||
|
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5)
|
||||||
|
func (c *Call) Times(i int) *Call {
|
||||||
|
c.lock()
|
||||||
|
defer c.unlock()
|
||||||
|
c.Repeatability = i
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WaitUntil sets the channel that will block the mock's return until its closed
|
||||||
|
// or a message is received.
|
||||||
|
//
|
||||||
|
// Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second))
|
||||||
|
func (c *Call) WaitUntil(w <-chan time.Time) *Call {
|
||||||
|
c.lock()
|
||||||
|
defer c.unlock()
|
||||||
|
c.WaitFor = w
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// After sets how long to block until the call returns
|
||||||
|
//
|
||||||
|
// Mock.On("MyMethod", arg1, arg2).After(time.Second)
|
||||||
|
func (c *Call) After(d time.Duration) *Call {
|
||||||
|
return c.WaitUntil(time.After(d))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run sets a handler to be called before returning. It can be used when
|
||||||
|
// mocking a method such as unmarshalers that takes a pointer to a struct and
|
||||||
|
// sets properties in such struct
|
||||||
|
//
|
||||||
|
// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}").Return().Run(func(args Arguments) {
|
||||||
|
// arg := args.Get(0).(*map[string]interface{})
|
||||||
|
// arg["foo"] = "bar"
|
||||||
|
// })
|
||||||
|
func (c *Call) Run(fn func(Arguments)) *Call {
|
||||||
|
c.lock()
|
||||||
|
defer c.unlock()
|
||||||
|
c.RunFn = fn
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// On chains a new expectation description onto the mocked interface. This
|
||||||
|
// allows syntax like.
|
||||||
|
//
|
||||||
|
// Mock.
|
||||||
|
// On("MyMethod", 1).Return(nil).
|
||||||
|
// On("MyOtherMethod", 'a', 'b', 'c').Return(errors.New("Some Error"))
|
||||||
|
func (c *Call) On(methodName string, arguments ...interface{}) *Call {
|
||||||
|
return c.Parent.On(methodName, arguments...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mock is the workhorse used to track activity on another object.
|
// Mock is the workhorse used to track activity on another object.
|
||||||
// For an example of its usage, refer to the "Example Usage" section at the top of this document.
|
// For an example of its usage, refer to the "Example Usage" section at the top
|
||||||
|
// of this document.
|
||||||
type Mock struct {
|
type Mock struct {
|
||||||
|
|
||||||
// The method name that is currently
|
|
||||||
// being referred to by the On method.
|
|
||||||
onMethodName string
|
|
||||||
|
|
||||||
// An array of the arguments that are
|
|
||||||
// currently being referred to by the On method.
|
|
||||||
onMethodArguments Arguments
|
|
||||||
|
|
||||||
// Represents the calls that are expected of
|
// Represents the calls that are expected of
|
||||||
// an object.
|
// an object.
|
||||||
ExpectedCalls []Call
|
ExpectedCalls []*Call
|
||||||
|
|
||||||
// Holds the calls that were made to this mocked object.
|
// Holds the calls that were made to this mocked object.
|
||||||
Calls []Call
|
Calls []Call
|
||||||
|
|
@ -95,103 +190,33 @@ func (m *Mock) TestData() objx.Map {
|
||||||
// being called.
|
// being called.
|
||||||
//
|
//
|
||||||
// Mock.On("MyMethod", arg1, arg2)
|
// Mock.On("MyMethod", arg1, arg2)
|
||||||
func (m *Mock) On(methodName string, arguments ...interface{}) *Mock {
|
func (m *Mock) On(methodName string, arguments ...interface{}) *Call {
|
||||||
m.onMethodName = methodName
|
|
||||||
m.onMethodArguments = arguments
|
|
||||||
|
|
||||||
for _, arg := range arguments {
|
for _, arg := range arguments {
|
||||||
if v := reflect.ValueOf(arg); v.Kind() == reflect.Func {
|
if v := reflect.ValueOf(arg); v.Kind() == reflect.Func {
|
||||||
panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg))
|
panic(fmt.Sprintf("cannot use Func in expectations. Use mock.AnythingOfType(\"%T\")", arg))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return finishes a description of an expectation of the method (and arguments)
|
|
||||||
// specified in the most recent On method call.
|
|
||||||
//
|
|
||||||
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2)
|
|
||||||
func (m *Mock) Return(returnArguments ...interface{}) *Mock {
|
|
||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
defer m.mutex.Unlock()
|
defer m.mutex.Unlock()
|
||||||
|
c := newCall(m, methodName, arguments...)
|
||||||
m.ExpectedCalls = append(m.ExpectedCalls, Call{m.onMethodName, m.onMethodArguments, returnArguments, 0, nil, nil})
|
m.ExpectedCalls = append(m.ExpectedCalls, c)
|
||||||
return m
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
// Once indicates that that the mock should only return the value once.
|
// /*
|
||||||
//
|
// Recording and responding to activity
|
||||||
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Once()
|
// */
|
||||||
func (m *Mock) Once() {
|
|
||||||
m.mutex.Lock()
|
|
||||||
m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = 1
|
|
||||||
m.mutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Twice indicates that that the mock should only return the value twice.
|
|
||||||
//
|
|
||||||
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Twice()
|
|
||||||
func (m *Mock) Twice() {
|
|
||||||
m.mutex.Lock()
|
|
||||||
m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = 2
|
|
||||||
m.mutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Times indicates that that the mock should only return the indicated number
|
|
||||||
// of times.
|
|
||||||
//
|
|
||||||
// Mock.On("MyMethod", arg1, arg2).Return(returnArg1, returnArg2).Times(5)
|
|
||||||
func (m *Mock) Times(i int) {
|
|
||||||
m.mutex.Lock()
|
|
||||||
m.ExpectedCalls[len(m.ExpectedCalls)-1].Repeatability = i
|
|
||||||
m.mutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// WaitUntil sets the channel that will block the mock's return until its closed
|
|
||||||
// or a message is received.
|
|
||||||
//
|
|
||||||
// Mock.On("MyMethod", arg1, arg2).WaitUntil(time.After(time.Second))
|
|
||||||
func (m *Mock) WaitUntil(w <-chan time.Time) *Mock {
|
|
||||||
m.mutex.Lock()
|
|
||||||
m.ExpectedCalls[len(m.ExpectedCalls)-1].WaitFor = w
|
|
||||||
m.mutex.Unlock()
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
// After sets how long to block until the call returns
|
|
||||||
//
|
|
||||||
// Mock.On("MyMethod", arg1, arg2).After(time.Second)
|
|
||||||
func (m *Mock) After(d time.Duration) *Mock {
|
|
||||||
return m.WaitUntil(time.After(d))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run sets a handler to be called before returning. It can be used when
|
|
||||||
// mocking a method such as unmarshalers that takes a pointer to a struct and
|
|
||||||
// sets properties in such struct
|
|
||||||
//
|
|
||||||
// Mock.On("Unmarshal", AnythingOfType("*map[string]interface{}").Return().Run(function(args Arguments) {
|
|
||||||
// arg := args.Get(0).(*map[string]interface{})
|
|
||||||
// arg["foo"] = "bar"
|
|
||||||
// })
|
|
||||||
func (m *Mock) Run(fn func(Arguments)) *Mock {
|
|
||||||
m.mutex.Lock()
|
|
||||||
m.ExpectedCalls[len(m.ExpectedCalls)-1].Run = fn
|
|
||||||
m.mutex.Unlock()
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Recording and responding to activity
|
|
||||||
*/
|
|
||||||
|
|
||||||
func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) {
|
func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *Call) {
|
||||||
for i, call := range m.expectedCalls() {
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
for i, call := range m.ExpectedCalls {
|
||||||
if call.Method == method && call.Repeatability > -1 {
|
if call.Method == method && call.Repeatability > -1 {
|
||||||
|
|
||||||
_, diffCount := call.Arguments.Diff(arguments)
|
_, diffCount := call.Arguments.Diff(arguments)
|
||||||
if diffCount == 0 {
|
if diffCount == 0 {
|
||||||
return i, &call
|
return i, call
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -201,7 +226,7 @@ func (m *Mock) findExpectedCall(method string, arguments ...interface{}) (int, *
|
||||||
|
|
||||||
func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *Call) {
|
func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *Call) {
|
||||||
diffCount := 0
|
diffCount := 0
|
||||||
var closestCall *Call = nil
|
var closestCall *Call
|
||||||
|
|
||||||
for _, call := range m.expectedCalls() {
|
for _, call := range m.expectedCalls() {
|
||||||
if call.Method == method {
|
if call.Method == method {
|
||||||
|
|
@ -209,7 +234,7 @@ func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *
|
||||||
_, tempDiffCount := call.Arguments.Diff(arguments)
|
_, tempDiffCount := call.Arguments.Diff(arguments)
|
||||||
if tempDiffCount < diffCount || diffCount == 0 {
|
if tempDiffCount < diffCount || diffCount == 0 {
|
||||||
diffCount = tempDiffCount
|
diffCount = tempDiffCount
|
||||||
closestCall = &call
|
closestCall = call
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -224,11 +249,11 @@ func (m *Mock) findClosestCall(method string, arguments ...interface{}) (bool, *
|
||||||
|
|
||||||
func callString(method string, arguments Arguments, includeArgumentValues bool) string {
|
func callString(method string, arguments Arguments, includeArgumentValues bool) string {
|
||||||
|
|
||||||
var argValsString string = ""
|
var argValsString string
|
||||||
if includeArgumentValues {
|
if includeArgumentValues {
|
||||||
var argVals []string
|
var argVals []string
|
||||||
for argIndex, arg := range arguments {
|
for argIndex, arg := range arguments {
|
||||||
argVals = append(argVals, fmt.Sprintf("%d: %v", argIndex, arg))
|
argVals = append(argVals, fmt.Sprintf("%d: %#v", argIndex, arg))
|
||||||
}
|
}
|
||||||
argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t"))
|
argValsString = fmt.Sprintf("\n\t\t%s", strings.Join(argVals, "\n\t\t"))
|
||||||
}
|
}
|
||||||
|
|
@ -247,6 +272,14 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
|
||||||
panic("Couldn't get the caller information")
|
panic("Couldn't get the caller information")
|
||||||
}
|
}
|
||||||
functionPath := runtime.FuncForPC(pc).Name()
|
functionPath := runtime.FuncForPC(pc).Name()
|
||||||
|
//Next four lines are required to use GCCGO function naming conventions.
|
||||||
|
//For Ex: github_com_docker_libkv_store_mock.WatchTree.pN39_github_com_docker_libkv_store_mock.Mock
|
||||||
|
//uses inteface information unlike golang github.com/docker/libkv/store/mock.(*Mock).WatchTree
|
||||||
|
//With GCCGO we need to remove interface information starting from pN<dd>.
|
||||||
|
re := regexp.MustCompile("\\.pN\\d+_")
|
||||||
|
if re.MatchString(functionPath) {
|
||||||
|
functionPath = re.Split(functionPath, -1)[0]
|
||||||
|
}
|
||||||
parts := strings.Split(functionPath, ".")
|
parts := strings.Split(functionPath, ".")
|
||||||
functionName := parts[len(parts)-1]
|
functionName := parts[len(parts)-1]
|
||||||
|
|
||||||
|
|
@ -272,17 +305,16 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
|
||||||
switch {
|
switch {
|
||||||
case call.Repeatability == 1:
|
case call.Repeatability == 1:
|
||||||
call.Repeatability = -1
|
call.Repeatability = -1
|
||||||
m.ExpectedCalls[found] = *call
|
|
||||||
case call.Repeatability > 1:
|
case call.Repeatability > 1:
|
||||||
call.Repeatability -= 1
|
call.Repeatability--
|
||||||
m.ExpectedCalls[found] = *call
|
|
||||||
}
|
}
|
||||||
m.mutex.Unlock()
|
m.mutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the call
|
// add the call
|
||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
m.Calls = append(m.Calls, Call{functionName, arguments, make([]interface{}, 0), 0, nil, nil})
|
m.Calls = append(m.Calls, *newCall(m, functionName, arguments...))
|
||||||
m.mutex.Unlock()
|
m.mutex.Unlock()
|
||||||
|
|
||||||
// block if specified
|
// block if specified
|
||||||
|
|
@ -290,12 +322,11 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
|
||||||
<-call.WaitFor
|
<-call.WaitFor
|
||||||
}
|
}
|
||||||
|
|
||||||
if call.Run != nil {
|
if call.RunFn != nil {
|
||||||
call.Run(arguments)
|
call.RunFn(arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
return call.ReturnArguments
|
return call.ReturnArguments
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -307,7 +338,7 @@ func (m *Mock) Called(arguments ...interface{}) Arguments {
|
||||||
//
|
//
|
||||||
// Calls may have occurred in any order.
|
// Calls may have occurred in any order.
|
||||||
func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
|
func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
|
||||||
var success bool = true
|
var success = true
|
||||||
for _, obj := range testObjects {
|
for _, obj := range testObjects {
|
||||||
mockObj := obj.(Mock)
|
mockObj := obj.(Mock)
|
||||||
success = success && mockObj.AssertExpectations(t)
|
success = success && mockObj.AssertExpectations(t)
|
||||||
|
|
@ -318,22 +349,25 @@ func AssertExpectationsForObjects(t TestingT, testObjects ...interface{}) bool {
|
||||||
// AssertExpectations asserts that everything specified with On and Return was
|
// AssertExpectations asserts that everything specified with On and Return was
|
||||||
// in fact called as expected. Calls may have occurred in any order.
|
// in fact called as expected. Calls may have occurred in any order.
|
||||||
func (m *Mock) AssertExpectations(t TestingT) bool {
|
func (m *Mock) AssertExpectations(t TestingT) bool {
|
||||||
var somethingMissing bool = false
|
var somethingMissing bool
|
||||||
var failedExpectations int = 0
|
var failedExpectations int
|
||||||
|
|
||||||
// iterate through each expectation
|
// iterate through each expectation
|
||||||
expectedCalls := m.expectedCalls()
|
expectedCalls := m.expectedCalls()
|
||||||
for _, expectedCall := range expectedCalls {
|
for _, expectedCall := range expectedCalls {
|
||||||
switch {
|
if !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments) {
|
||||||
case !m.methodWasCalled(expectedCall.Method, expectedCall.Arguments):
|
|
||||||
somethingMissing = true
|
somethingMissing = true
|
||||||
failedExpectations++
|
failedExpectations++
|
||||||
t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
|
t.Logf("\u274C\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
|
||||||
case expectedCall.Repeatability > 0:
|
} else {
|
||||||
somethingMissing = true
|
m.mutex.Lock()
|
||||||
failedExpectations++
|
if expectedCall.Repeatability > 0 {
|
||||||
default:
|
somethingMissing = true
|
||||||
t.Logf("\u2705\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
|
failedExpectations++
|
||||||
|
} else {
|
||||||
|
t.Logf("\u2705\t%s(%s)", expectedCall.Method, expectedCall.Arguments.String())
|
||||||
|
}
|
||||||
|
m.mutex.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -346,13 +380,13 @@ func (m *Mock) AssertExpectations(t TestingT) bool {
|
||||||
|
|
||||||
// AssertNumberOfCalls asserts that the method was called expectedCalls times.
|
// AssertNumberOfCalls asserts that the method was called expectedCalls times.
|
||||||
func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool {
|
func (m *Mock) AssertNumberOfCalls(t TestingT, methodName string, expectedCalls int) bool {
|
||||||
var actualCalls int = 0
|
var actualCalls int
|
||||||
for _, call := range m.calls() {
|
for _, call := range m.calls() {
|
||||||
if call.Method == methodName {
|
if call.Method == methodName {
|
||||||
actualCalls++
|
actualCalls++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return assert.Equal(t, actualCalls, expectedCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls))
|
return assert.Equal(t, expectedCalls, actualCalls, fmt.Sprintf("Expected number of calls (%d) does not match the actual number of calls (%d).", expectedCalls, actualCalls))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssertCalled asserts that the method was called.
|
// AssertCalled asserts that the method was called.
|
||||||
|
|
@ -390,10 +424,10 @@ func (m *Mock) methodWasCalled(methodName string, expected []interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mock) expectedCalls() []Call {
|
func (m *Mock) expectedCalls() []*Call {
|
||||||
m.mutex.Lock()
|
m.mutex.Lock()
|
||||||
defer m.mutex.Unlock()
|
defer m.mutex.Unlock()
|
||||||
return append([]Call{}, m.ExpectedCalls...)
|
return append([]*Call{}, m.ExpectedCalls...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mock) calls() []Call {
|
func (m *Mock) calls() []Call {
|
||||||
|
|
@ -410,8 +444,8 @@ func (m *Mock) calls() []Call {
|
||||||
type Arguments []interface{}
|
type Arguments []interface{}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// The "any" argument. Used in Diff and Assert when
|
// Anything is used in Diff and Assert when the argument being tested
|
||||||
// the argument being tested shouldn't be taken into consideration.
|
// shouldn't be taken into consideration.
|
||||||
Anything string = "mock.Anything"
|
Anything string = "mock.Anything"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -428,6 +462,54 @@ func AnythingOfType(t string) AnythingOfTypeArgument {
|
||||||
return AnythingOfTypeArgument(t)
|
return AnythingOfTypeArgument(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// argumentMatcher performs custom argument matching, returning whether or
|
||||||
|
// not the argument is matched by the expectation fixture function.
|
||||||
|
type argumentMatcher struct {
|
||||||
|
// fn is a function which accepts one argument, and returns a bool.
|
||||||
|
fn reflect.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f argumentMatcher) Matches(argument interface{}) bool {
|
||||||
|
expectType := f.fn.Type().In(0)
|
||||||
|
|
||||||
|
if reflect.TypeOf(argument).AssignableTo(expectType) {
|
||||||
|
result := f.fn.Call([]reflect.Value{reflect.ValueOf(argument)})
|
||||||
|
return result[0].Bool()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f argumentMatcher) String() string {
|
||||||
|
return fmt.Sprintf("func(%s) bool", f.fn.Type().In(0).Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchedBy can be used to match a mock call based on only certain properties
|
||||||
|
// from a complex struct or some calculation. It takes a function that will be
|
||||||
|
// evaluated with the called argument and will return true when there's a match
|
||||||
|
// and false otherwise.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
// m.On("Do", func(req *http.Request) bool { return req.Host == "example.com" })
|
||||||
|
//
|
||||||
|
// |fn|, must be a function accepting a single argument (of the expected type)
|
||||||
|
// which returns a bool. If |fn| doesn't match the required signature,
|
||||||
|
// MathedBy() panics.
|
||||||
|
func MatchedBy(fn interface{}) argumentMatcher {
|
||||||
|
fnType := reflect.TypeOf(fn)
|
||||||
|
|
||||||
|
if fnType.Kind() != reflect.Func {
|
||||||
|
panic(fmt.Sprintf("assert: arguments: %s is not a func", fn))
|
||||||
|
}
|
||||||
|
if fnType.NumIn() != 1 {
|
||||||
|
panic(fmt.Sprintf("assert: arguments: %s does not take exactly one argument", fn))
|
||||||
|
}
|
||||||
|
if fnType.NumOut() != 1 || fnType.Out(0).Kind() != reflect.Bool {
|
||||||
|
panic(fmt.Sprintf("assert: arguments: %s does not return a bool", fn))
|
||||||
|
}
|
||||||
|
|
||||||
|
return argumentMatcher{fn: reflect.ValueOf(fn)}
|
||||||
|
}
|
||||||
|
|
||||||
// Get Returns the argument at the specified index.
|
// Get Returns the argument at the specified index.
|
||||||
func (args Arguments) Get(index int) interface{} {
|
func (args Arguments) Get(index int) interface{} {
|
||||||
if index+1 > len(args) {
|
if index+1 > len(args) {
|
||||||
|
|
@ -452,10 +534,10 @@ func (args Arguments) Is(objects ...interface{}) bool {
|
||||||
// Returns the diff string and number of differences found.
|
// Returns the diff string and number of differences found.
|
||||||
func (args Arguments) Diff(objects []interface{}) (string, int) {
|
func (args Arguments) Diff(objects []interface{}) (string, int) {
|
||||||
|
|
||||||
var output string = "\n"
|
var output = "\n"
|
||||||
var differences int
|
var differences int
|
||||||
|
|
||||||
var maxArgCount int = len(args)
|
var maxArgCount = len(args)
|
||||||
if len(objects) > maxArgCount {
|
if len(objects) > maxArgCount {
|
||||||
maxArgCount = len(objects)
|
maxArgCount = len(objects)
|
||||||
}
|
}
|
||||||
|
|
@ -475,7 +557,14 @@ func (args Arguments) Diff(objects []interface{}) (string, int) {
|
||||||
expected = args[i]
|
expected = args[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
|
if matcher, ok := expected.(argumentMatcher); ok {
|
||||||
|
if matcher.Matches(actual) {
|
||||||
|
output = fmt.Sprintf("%s\t%d: \u2705 %s matched by %s\n", output, i, actual, matcher)
|
||||||
|
} else {
|
||||||
|
differences++
|
||||||
|
output = fmt.Sprintf("%s\t%d: \u2705 %s not matched by %s\n", output, i, actual, matcher)
|
||||||
|
}
|
||||||
|
} else if reflect.TypeOf(expected) == reflect.TypeOf((*AnythingOfTypeArgument)(nil)).Elem() {
|
||||||
|
|
||||||
// type checking
|
// type checking
|
||||||
if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) {
|
if reflect.TypeOf(actual).Name() != string(expected.(AnythingOfTypeArgument)) && reflect.TypeOf(actual).String() != string(expected.(AnythingOfTypeArgument)) {
|
||||||
|
|
@ -543,7 +632,7 @@ func (args Arguments) String(indexOrNil ...int) string {
|
||||||
return strings.Join(argsStr, ",")
|
return strings.Join(argsStr, ",")
|
||||||
} else if len(indexOrNil) == 1 {
|
} else if len(indexOrNil) == 1 {
|
||||||
// Index has been specified - get the argument at that index
|
// Index has been specified - get the argument at that index
|
||||||
var index int = indexOrNil[0]
|
var index = indexOrNil[0]
|
||||||
var s string
|
var s string
|
||||||
var ok bool
|
var ok bool
|
||||||
if s, ok = args.Get(index).(string); !ok {
|
if s, ok = args.Get(index).(string); !ok {
|
||||||
|
|
|
||||||
556
Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go
generated
vendored
556
Godeps/_workspace/src/github.com/stretchr/testify/mock/mock_test.go
generated
vendored
|
|
@ -3,6 +3,7 @@ package mock
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -67,62 +68,154 @@ func (i *TestExampleImplementation) TheExampleMethodFuncType(fn ExampleFuncType)
|
||||||
|
|
||||||
func Test_Mock_TestData(t *testing.T) {
|
func Test_Mock_TestData(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
if assert.NotNil(t, mockedService.TestData()) {
|
if assert.NotNil(t, mockedService.TestData()) {
|
||||||
|
|
||||||
mockedService.TestData().Set("something", 123)
|
mockedService.TestData().Set("something", 123)
|
||||||
assert.Equal(t, 123, mockedService.TestData().Get("something").Data())
|
assert.Equal(t, 123, mockedService.TestData().Get("something").Data())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_On(t *testing.T) {
|
func Test_Mock_On(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
assert.Equal(t, mockedService.On("TheExampleMethod"), &mockedService.Mock)
|
c := mockedService.On("TheExampleMethod")
|
||||||
assert.Equal(t, "TheExampleMethod", mockedService.onMethodName)
|
assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
|
assert.Equal(t, "TheExampleMethod", c.Method)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Mock_Chained_On(t *testing.T) {
|
||||||
|
// make a test impl object
|
||||||
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
|
mockedService.
|
||||||
|
On("TheExampleMethod", 1, 2, 3).
|
||||||
|
Return(0).
|
||||||
|
On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).
|
||||||
|
Return(nil)
|
||||||
|
|
||||||
|
expectedCalls := []*Call{
|
||||||
|
&Call{
|
||||||
|
Parent: &mockedService.Mock,
|
||||||
|
Method: "TheExampleMethod",
|
||||||
|
Arguments: []interface{}{1, 2, 3},
|
||||||
|
ReturnArguments: []interface{}{0},
|
||||||
|
},
|
||||||
|
&Call{
|
||||||
|
Parent: &mockedService.Mock,
|
||||||
|
Method: "TheExampleMethod3",
|
||||||
|
Arguments: []interface{}{AnythingOfType("*mock.ExampleType")},
|
||||||
|
ReturnArguments: []interface{}{nil},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, expectedCalls, mockedService.ExpectedCalls)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_On_WithArgs(t *testing.T) {
|
func Test_Mock_On_WithArgs(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
assert.Equal(t, mockedService.On("TheExampleMethod", 1, 2, 3), &mockedService.Mock)
|
c := mockedService.On("TheExampleMethod", 1, 2, 3, 4)
|
||||||
assert.Equal(t, "TheExampleMethod", mockedService.onMethodName)
|
|
||||||
assert.Equal(t, 1, mockedService.onMethodArguments[0])
|
|
||||||
assert.Equal(t, 2, mockedService.onMethodArguments[1])
|
|
||||||
assert.Equal(t, 3, mockedService.onMethodArguments[2])
|
|
||||||
|
|
||||||
|
assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
|
assert.Equal(t, "TheExampleMethod", c.Method)
|
||||||
|
assert.Equal(t, Arguments{1, 2, 3, 4}, c.Arguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_On_WithFuncArg(t *testing.T) {
|
func Test_Mock_On_WithFuncArg(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
assert.Equal(t, mockedService.On("TheExampleMethodFunc", AnythingOfType("func(string) error")).Return(nil), &mockedService.Mock)
|
c := mockedService.
|
||||||
assert.Equal(t, "TheExampleMethodFunc", mockedService.onMethodName)
|
On("TheExampleMethodFunc", AnythingOfType("func(string) error")).
|
||||||
assert.Equal(t, AnythingOfType("func(string) error"), mockedService.onMethodArguments[0])
|
Return(nil)
|
||||||
|
|
||||||
|
assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
|
assert.Equal(t, "TheExampleMethodFunc", c.Method)
|
||||||
|
assert.Equal(t, 1, len(c.Arguments))
|
||||||
|
assert.Equal(t, AnythingOfType("func(string) error"), c.Arguments[0])
|
||||||
|
|
||||||
fn := func(string) error { return nil }
|
fn := func(string) error { return nil }
|
||||||
mockedService.TheExampleMethodFunc(fn)
|
|
||||||
|
|
||||||
|
assert.NotPanics(t, func() {
|
||||||
|
mockedService.TheExampleMethodFunc(fn)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Mock_On_WithIntArgMatcher(t *testing.T) {
|
||||||
|
var mockedService TestExampleImplementation
|
||||||
|
|
||||||
|
mockedService.On("TheExampleMethod",
|
||||||
|
MatchedBy(func(a int) bool {
|
||||||
|
return a == 1
|
||||||
|
}), MatchedBy(func(b int) bool {
|
||||||
|
return b == 2
|
||||||
|
}), MatchedBy(func(c int) bool {
|
||||||
|
return c == 3
|
||||||
|
})).Return(0, nil)
|
||||||
|
|
||||||
|
assert.Panics(t, func() {
|
||||||
|
mockedService.TheExampleMethod(1, 2, 4)
|
||||||
|
})
|
||||||
|
assert.Panics(t, func() {
|
||||||
|
mockedService.TheExampleMethod(2, 2, 3)
|
||||||
|
})
|
||||||
|
assert.NotPanics(t, func() {
|
||||||
|
mockedService.TheExampleMethod(1, 2, 3)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Mock_On_WithPtrArgMatcher(t *testing.T) {
|
||||||
|
var mockedService TestExampleImplementation
|
||||||
|
|
||||||
|
mockedService.On("TheExampleMethod3",
|
||||||
|
MatchedBy(func(a *ExampleType) bool { return a.ran == true }),
|
||||||
|
).Return(nil)
|
||||||
|
|
||||||
|
mockedService.On("TheExampleMethod3",
|
||||||
|
MatchedBy(func(a *ExampleType) bool { return a.ran == false }),
|
||||||
|
).Return(errors.New("error"))
|
||||||
|
|
||||||
|
assert.Equal(t, mockedService.TheExampleMethod3(&ExampleType{true}), nil)
|
||||||
|
assert.EqualError(t, mockedService.TheExampleMethod3(&ExampleType{false}), "error")
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Mock_On_WithFuncArgMatcher(t *testing.T) {
|
||||||
|
var mockedService TestExampleImplementation
|
||||||
|
|
||||||
|
fixture1, fixture2 := errors.New("fixture1"), errors.New("fixture2")
|
||||||
|
|
||||||
|
mockedService.On("TheExampleMethodFunc",
|
||||||
|
MatchedBy(func(a func(string) error) bool { return a("string") == fixture1 }),
|
||||||
|
).Return(errors.New("fixture1"))
|
||||||
|
|
||||||
|
mockedService.On("TheExampleMethodFunc",
|
||||||
|
MatchedBy(func(a func(string) error) bool { return a("string") == fixture2 }),
|
||||||
|
).Return(errors.New("fixture2"))
|
||||||
|
|
||||||
|
assert.EqualError(t, mockedService.TheExampleMethodFunc(
|
||||||
|
func(string) error { return fixture1 }), "fixture1")
|
||||||
|
assert.EqualError(t, mockedService.TheExampleMethodFunc(
|
||||||
|
func(string) error { return fixture2 }), "fixture2")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_On_WithVariadicFunc(t *testing.T) {
|
func Test_Mock_On_WithVariadicFunc(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
assert.Equal(t, mockedService.On("TheExampleMethodVariadic", []int{1, 2, 3}).Return(nil), &mockedService.Mock)
|
c := mockedService.
|
||||||
assert.Equal(t, "TheExampleMethodVariadic", mockedService.onMethodName)
|
On("TheExampleMethodVariadic", []int{1, 2, 3}).
|
||||||
assert.Equal(t, []int{1, 2, 3}, mockedService.onMethodArguments[0])
|
Return(nil)
|
||||||
|
|
||||||
|
assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
|
assert.Equal(t, 1, len(c.Arguments))
|
||||||
|
assert.Equal(t, []int{1, 2, 3}, c.Arguments[0])
|
||||||
|
|
||||||
assert.NotPanics(t, func() {
|
assert.NotPanics(t, func() {
|
||||||
mockedService.TheExampleMethodVariadic(1, 2, 3)
|
mockedService.TheExampleMethodVariadic(1, 2, 3)
|
||||||
|
|
@ -136,11 +229,14 @@ func Test_Mock_On_WithVariadicFunc(t *testing.T) {
|
||||||
func Test_Mock_On_WithVariadicFuncWithInterface(t *testing.T) {
|
func Test_Mock_On_WithVariadicFuncWithInterface(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
assert.Equal(t, mockedService.On("TheExampleMethodVariadicInterface", []interface{}{1, 2, 3}).Return(nil), &mockedService.Mock)
|
c := mockedService.On("TheExampleMethodVariadicInterface", []interface{}{1, 2, 3}).
|
||||||
assert.Equal(t, "TheExampleMethodVariadicInterface", mockedService.onMethodName)
|
Return(nil)
|
||||||
assert.Equal(t, []interface{}{1, 2, 3}, mockedService.onMethodArguments[0])
|
|
||||||
|
assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
|
assert.Equal(t, 1, len(c.Arguments))
|
||||||
|
assert.Equal(t, []interface{}{1, 2, 3}, c.Arguments[0])
|
||||||
|
|
||||||
assert.NotPanics(t, func() {
|
assert.NotPanics(t, func() {
|
||||||
mockedService.TheExampleMethodVariadicInterface(1, 2, 3)
|
mockedService.TheExampleMethodVariadicInterface(1, 2, 3)
|
||||||
|
|
@ -154,12 +250,16 @@ func Test_Mock_On_WithVariadicFuncWithInterface(t *testing.T) {
|
||||||
func Test_Mock_On_WithVariadicFuncWithEmptyInterfaceArray(t *testing.T) {
|
func Test_Mock_On_WithVariadicFuncWithEmptyInterfaceArray(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
var expected []interface{}
|
var expected []interface{}
|
||||||
assert.Equal(t, mockedService.On("TheExampleMethodVariadicInterface", expected).Return(nil), &mockedService.Mock)
|
c := mockedService.
|
||||||
assert.Equal(t, "TheExampleMethodVariadicInterface", mockedService.onMethodName)
|
On("TheExampleMethodVariadicInterface", expected).
|
||||||
assert.Equal(t, expected, mockedService.onMethodArguments[0])
|
Return(nil)
|
||||||
|
|
||||||
|
assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
|
assert.Equal(t, 1, len(c.Arguments))
|
||||||
|
assert.Equal(t, expected, c.Arguments[0])
|
||||||
|
|
||||||
assert.NotPanics(t, func() {
|
assert.NotPanics(t, func() {
|
||||||
mockedService.TheExampleMethodVariadicInterface()
|
mockedService.TheExampleMethodVariadicInterface()
|
||||||
|
|
@ -172,7 +272,7 @@ func Test_Mock_On_WithVariadicFuncWithEmptyInterfaceArray(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_On_WithFuncPanics(t *testing.T) {
|
func Test_Mock_On_WithFuncPanics(t *testing.T) {
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
assert.Panics(t, func() {
|
||||||
mockedService.On("TheExampleMethodFunc", func(string) error { return nil })
|
mockedService.On("TheExampleMethodFunc", func(string) error { return nil })
|
||||||
|
|
@ -182,217 +282,248 @@ func Test_Mock_On_WithFuncPanics(t *testing.T) {
|
||||||
func Test_Mock_On_WithFuncTypeArg(t *testing.T) {
|
func Test_Mock_On_WithFuncTypeArg(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
assert.Equal(t, mockedService.On("TheExampleMethodFuncType", AnythingOfType("mock.ExampleFuncType")).Return(nil), &mockedService.Mock)
|
c := mockedService.
|
||||||
assert.Equal(t, "TheExampleMethodFuncType", mockedService.onMethodName)
|
On("TheExampleMethodFuncType", AnythingOfType("mock.ExampleFuncType")).
|
||||||
assert.Equal(t, AnythingOfType("mock.ExampleFuncType"), mockedService.onMethodArguments[0])
|
Return(nil)
|
||||||
|
|
||||||
|
assert.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
|
assert.Equal(t, 1, len(c.Arguments))
|
||||||
|
assert.Equal(t, AnythingOfType("mock.ExampleFuncType"), c.Arguments[0])
|
||||||
|
|
||||||
fn := func(string) error { return nil }
|
fn := func(string) error { return nil }
|
||||||
mockedService.TheExampleMethodFuncType(fn)
|
assert.NotPanics(t, func() {
|
||||||
|
mockedService.TheExampleMethodFuncType(fn)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_Return(t *testing.T) {
|
func Test_Mock_Return(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
assert.Equal(t, mockedService.On("TheExampleMethod", "A", "B", true).Return(1, "two", true), &mockedService.Mock)
|
c := mockedService.
|
||||||
|
On("TheExampleMethod", "A", "B", true).
|
||||||
|
Return(1, "two", true)
|
||||||
|
|
||||||
// ensure the call was created
|
require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
if assert.Equal(t, 1, len(mockedService.ExpectedCalls)) {
|
|
||||||
call := mockedService.ExpectedCalls[0]
|
|
||||||
|
|
||||||
assert.Equal(t, "TheExampleMethod", call.Method)
|
call := mockedService.ExpectedCalls[0]
|
||||||
assert.Equal(t, "A", call.Arguments[0])
|
|
||||||
assert.Equal(t, "B", call.Arguments[1])
|
|
||||||
assert.Equal(t, true, call.Arguments[2])
|
|
||||||
assert.Equal(t, 1, call.ReturnArguments[0])
|
|
||||||
assert.Equal(t, "two", call.ReturnArguments[1])
|
|
||||||
assert.Equal(t, true, call.ReturnArguments[2])
|
|
||||||
assert.Equal(t, 0, call.Repeatability)
|
|
||||||
assert.Nil(t, call.WaitFor)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assert.Equal(t, "TheExampleMethod", call.Method)
|
||||||
|
assert.Equal(t, "A", call.Arguments[0])
|
||||||
|
assert.Equal(t, "B", call.Arguments[1])
|
||||||
|
assert.Equal(t, true, call.Arguments[2])
|
||||||
|
assert.Equal(t, 1, call.ReturnArguments[0])
|
||||||
|
assert.Equal(t, "two", call.ReturnArguments[1])
|
||||||
|
assert.Equal(t, true, call.ReturnArguments[2])
|
||||||
|
assert.Equal(t, 0, call.Repeatability)
|
||||||
|
assert.Nil(t, call.WaitFor)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_Return_WaitUntil(t *testing.T) {
|
func Test_Mock_Return_WaitUntil(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
ch := time.After(time.Second)
|
ch := time.After(time.Second)
|
||||||
|
|
||||||
assert.Equal(t, mockedService.Mock.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).WaitUntil(ch), &mockedService.Mock)
|
c := mockedService.Mock.
|
||||||
|
On("TheExampleMethod", "A", "B", true).
|
||||||
|
WaitUntil(ch).
|
||||||
|
Return(1, "two", true)
|
||||||
|
|
||||||
// ensure the call was created
|
// assert that the call was created
|
||||||
if assert.Equal(t, 1, len(mockedService.Mock.ExpectedCalls)) {
|
require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
call := mockedService.Mock.ExpectedCalls[0]
|
|
||||||
|
|
||||||
assert.Equal(t, "TheExampleMethod", call.Method)
|
call := mockedService.ExpectedCalls[0]
|
||||||
assert.Equal(t, "A", call.Arguments[0])
|
|
||||||
assert.Equal(t, "B", call.Arguments[1])
|
|
||||||
assert.Equal(t, true, call.Arguments[2])
|
|
||||||
assert.Equal(t, 1, call.ReturnArguments[0])
|
|
||||||
assert.Equal(t, "two", call.ReturnArguments[1])
|
|
||||||
assert.Equal(t, true, call.ReturnArguments[2])
|
|
||||||
assert.Equal(t, 0, call.Repeatability)
|
|
||||||
assert.Equal(t, ch, call.WaitFor)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assert.Equal(t, "TheExampleMethod", call.Method)
|
||||||
|
assert.Equal(t, "A", call.Arguments[0])
|
||||||
|
assert.Equal(t, "B", call.Arguments[1])
|
||||||
|
assert.Equal(t, true, call.Arguments[2])
|
||||||
|
assert.Equal(t, 1, call.ReturnArguments[0])
|
||||||
|
assert.Equal(t, "two", call.ReturnArguments[1])
|
||||||
|
assert.Equal(t, true, call.ReturnArguments[2])
|
||||||
|
assert.Equal(t, 0, call.Repeatability)
|
||||||
|
assert.Equal(t, ch, call.WaitFor)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_Return_After(t *testing.T) {
|
func Test_Mock_Return_After(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
assert.Equal(t, mockedService.Mock.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).After(time.Second), &mockedService.Mock)
|
c := mockedService.Mock.
|
||||||
|
On("TheExampleMethod", "A", "B", true).
|
||||||
|
Return(1, "two", true).
|
||||||
|
After(time.Second)
|
||||||
|
|
||||||
// ensure the call was created
|
require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
if assert.Equal(t, 1, len(mockedService.Mock.ExpectedCalls)) {
|
|
||||||
call := mockedService.Mock.ExpectedCalls[0]
|
|
||||||
|
|
||||||
assert.Equal(t, "TheExampleMethod", call.Method)
|
call := mockedService.Mock.ExpectedCalls[0]
|
||||||
assert.Equal(t, "A", call.Arguments[0])
|
|
||||||
assert.Equal(t, "B", call.Arguments[1])
|
|
||||||
assert.Equal(t, true, call.Arguments[2])
|
|
||||||
assert.Equal(t, 1, call.ReturnArguments[0])
|
|
||||||
assert.Equal(t, "two", call.ReturnArguments[1])
|
|
||||||
assert.Equal(t, true, call.ReturnArguments[2])
|
|
||||||
assert.Equal(t, 0, call.Repeatability)
|
|
||||||
assert.NotEqual(t, nil, call.WaitFor)
|
|
||||||
|
|
||||||
}
|
assert.Equal(t, "TheExampleMethod", call.Method)
|
||||||
|
assert.Equal(t, "A", call.Arguments[0])
|
||||||
|
assert.Equal(t, "B", call.Arguments[1])
|
||||||
|
assert.Equal(t, true, call.Arguments[2])
|
||||||
|
assert.Equal(t, 1, call.ReturnArguments[0])
|
||||||
|
assert.Equal(t, "two", call.ReturnArguments[1])
|
||||||
|
assert.Equal(t, true, call.ReturnArguments[2])
|
||||||
|
assert.Equal(t, 0, call.Repeatability)
|
||||||
|
assert.NotEqual(t, nil, call.WaitFor)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_Return_Run(t *testing.T) {
|
func Test_Mock_Return_Run(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
assert.Equal(t, mockedService.Mock.On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).Return(nil).Run(func(args Arguments) {
|
fn := func(args Arguments) {
|
||||||
arg := args.Get(0).(*ExampleType)
|
arg := args.Get(0).(*ExampleType)
|
||||||
arg.ran = true
|
arg.ran = true
|
||||||
}), &mockedService.Mock)
|
|
||||||
|
|
||||||
// ensure the call was created
|
|
||||||
if assert.Equal(t, 1, len(mockedService.Mock.ExpectedCalls)) {
|
|
||||||
call := mockedService.Mock.ExpectedCalls[0]
|
|
||||||
|
|
||||||
assert.Equal(t, "TheExampleMethod3", call.Method)
|
|
||||||
assert.Equal(t, AnythingOfType("*mock.ExampleType"), call.Arguments[0])
|
|
||||||
assert.Equal(t, nil, call.ReturnArguments[0])
|
|
||||||
assert.Equal(t, 0, call.Repeatability)
|
|
||||||
assert.NotEqual(t, nil, call.WaitFor)
|
|
||||||
assert.NotNil(t, call.Run)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c := mockedService.Mock.
|
||||||
|
On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).
|
||||||
|
Return(nil).
|
||||||
|
Run(fn)
|
||||||
|
|
||||||
|
require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
|
|
||||||
|
call := mockedService.Mock.ExpectedCalls[0]
|
||||||
|
|
||||||
|
assert.Equal(t, "TheExampleMethod3", call.Method)
|
||||||
|
assert.Equal(t, AnythingOfType("*mock.ExampleType"), call.Arguments[0])
|
||||||
|
assert.Equal(t, nil, call.ReturnArguments[0])
|
||||||
|
assert.Equal(t, 0, call.Repeatability)
|
||||||
|
assert.NotEqual(t, nil, call.WaitFor)
|
||||||
|
assert.NotNil(t, call.Run)
|
||||||
|
|
||||||
et := ExampleType{}
|
et := ExampleType{}
|
||||||
assert.Equal(t, false, et.ran)
|
assert.Equal(t, false, et.ran)
|
||||||
mockedService.TheExampleMethod3(&et)
|
mockedService.TheExampleMethod3(&et)
|
||||||
assert.Equal(t, true, et.ran)
|
assert.Equal(t, true, et.ran)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Mock_Return_Run_Out_Of_Order(t *testing.T) {
|
||||||
|
// make a test impl object
|
||||||
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
f := func(args Arguments) {
|
||||||
|
arg := args.Get(0).(*ExampleType)
|
||||||
|
arg.ran = true
|
||||||
|
}
|
||||||
|
|
||||||
|
c := mockedService.Mock.
|
||||||
|
On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).
|
||||||
|
Run(f).
|
||||||
|
Return(nil)
|
||||||
|
|
||||||
|
require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
|
|
||||||
|
call := mockedService.Mock.ExpectedCalls[0]
|
||||||
|
|
||||||
|
assert.Equal(t, "TheExampleMethod3", call.Method)
|
||||||
|
assert.Equal(t, AnythingOfType("*mock.ExampleType"), call.Arguments[0])
|
||||||
|
assert.Equal(t, nil, call.ReturnArguments[0])
|
||||||
|
assert.Equal(t, 0, call.Repeatability)
|
||||||
|
assert.NotEqual(t, nil, call.WaitFor)
|
||||||
|
assert.NotNil(t, call.Run)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_Return_Once(t *testing.T) {
|
func Test_Mock_Return_Once(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).Once()
|
c := mockedService.On("TheExampleMethod", "A", "B", true).
|
||||||
|
Return(1, "two", true).
|
||||||
|
Once()
|
||||||
|
|
||||||
// ensure the call was created
|
require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
if assert.Equal(t, 1, len(mockedService.ExpectedCalls)) {
|
|
||||||
call := mockedService.ExpectedCalls[0]
|
|
||||||
|
|
||||||
assert.Equal(t, "TheExampleMethod", call.Method)
|
call := mockedService.ExpectedCalls[0]
|
||||||
assert.Equal(t, "A", call.Arguments[0])
|
|
||||||
assert.Equal(t, "B", call.Arguments[1])
|
|
||||||
assert.Equal(t, true, call.Arguments[2])
|
|
||||||
assert.Equal(t, 1, call.ReturnArguments[0])
|
|
||||||
assert.Equal(t, "two", call.ReturnArguments[1])
|
|
||||||
assert.Equal(t, true, call.ReturnArguments[2])
|
|
||||||
assert.Equal(t, 1, call.Repeatability)
|
|
||||||
assert.Nil(t, call.WaitFor)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assert.Equal(t, "TheExampleMethod", call.Method)
|
||||||
|
assert.Equal(t, "A", call.Arguments[0])
|
||||||
|
assert.Equal(t, "B", call.Arguments[1])
|
||||||
|
assert.Equal(t, true, call.Arguments[2])
|
||||||
|
assert.Equal(t, 1, call.ReturnArguments[0])
|
||||||
|
assert.Equal(t, "two", call.ReturnArguments[1])
|
||||||
|
assert.Equal(t, true, call.ReturnArguments[2])
|
||||||
|
assert.Equal(t, 1, call.Repeatability)
|
||||||
|
assert.Nil(t, call.WaitFor)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_Return_Twice(t *testing.T) {
|
func Test_Mock_Return_Twice(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).Twice()
|
c := mockedService.
|
||||||
|
On("TheExampleMethod", "A", "B", true).
|
||||||
|
Return(1, "two", true).
|
||||||
|
Twice()
|
||||||
|
|
||||||
// ensure the call was created
|
require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
if assert.Equal(t, 1, len(mockedService.ExpectedCalls)) {
|
|
||||||
call := mockedService.ExpectedCalls[0]
|
|
||||||
|
|
||||||
assert.Equal(t, "TheExampleMethod", call.Method)
|
call := mockedService.ExpectedCalls[0]
|
||||||
assert.Equal(t, "A", call.Arguments[0])
|
|
||||||
assert.Equal(t, "B", call.Arguments[1])
|
|
||||||
assert.Equal(t, true, call.Arguments[2])
|
|
||||||
assert.Equal(t, 1, call.ReturnArguments[0])
|
|
||||||
assert.Equal(t, "two", call.ReturnArguments[1])
|
|
||||||
assert.Equal(t, true, call.ReturnArguments[2])
|
|
||||||
assert.Equal(t, 2, call.Repeatability)
|
|
||||||
assert.Nil(t, call.WaitFor)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assert.Equal(t, "TheExampleMethod", call.Method)
|
||||||
|
assert.Equal(t, "A", call.Arguments[0])
|
||||||
|
assert.Equal(t, "B", call.Arguments[1])
|
||||||
|
assert.Equal(t, true, call.Arguments[2])
|
||||||
|
assert.Equal(t, 1, call.ReturnArguments[0])
|
||||||
|
assert.Equal(t, "two", call.ReturnArguments[1])
|
||||||
|
assert.Equal(t, true, call.ReturnArguments[2])
|
||||||
|
assert.Equal(t, 2, call.Repeatability)
|
||||||
|
assert.Nil(t, call.WaitFor)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_Return_Times(t *testing.T) {
|
func Test_Mock_Return_Times(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("TheExampleMethod", "A", "B", true).Return(1, "two", true).Times(5)
|
c := mockedService.
|
||||||
|
On("TheExampleMethod", "A", "B", true).
|
||||||
|
Return(1, "two", true).
|
||||||
|
Times(5)
|
||||||
|
|
||||||
// ensure the call was created
|
require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
if assert.Equal(t, 1, len(mockedService.ExpectedCalls)) {
|
|
||||||
call := mockedService.ExpectedCalls[0]
|
|
||||||
|
|
||||||
assert.Equal(t, "TheExampleMethod", call.Method)
|
call := mockedService.ExpectedCalls[0]
|
||||||
assert.Equal(t, "A", call.Arguments[0])
|
|
||||||
assert.Equal(t, "B", call.Arguments[1])
|
|
||||||
assert.Equal(t, true, call.Arguments[2])
|
|
||||||
assert.Equal(t, 1, call.ReturnArguments[0])
|
|
||||||
assert.Equal(t, "two", call.ReturnArguments[1])
|
|
||||||
assert.Equal(t, true, call.ReturnArguments[2])
|
|
||||||
assert.Equal(t, 5, call.Repeatability)
|
|
||||||
assert.Nil(t, call.WaitFor)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assert.Equal(t, "TheExampleMethod", call.Method)
|
||||||
|
assert.Equal(t, "A", call.Arguments[0])
|
||||||
|
assert.Equal(t, "B", call.Arguments[1])
|
||||||
|
assert.Equal(t, true, call.Arguments[2])
|
||||||
|
assert.Equal(t, 1, call.ReturnArguments[0])
|
||||||
|
assert.Equal(t, "two", call.ReturnArguments[1])
|
||||||
|
assert.Equal(t, true, call.ReturnArguments[2])
|
||||||
|
assert.Equal(t, 5, call.Repeatability)
|
||||||
|
assert.Nil(t, call.WaitFor)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_Return_Nothing(t *testing.T) {
|
func Test_Mock_Return_Nothing(t *testing.T) {
|
||||||
|
|
||||||
// make a test impl object
|
// make a test impl object
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
assert.Equal(t, mockedService.On("TheExampleMethod", "A", "B", true).Return(), &mockedService.Mock)
|
c := mockedService.
|
||||||
|
On("TheExampleMethod", "A", "B", true).
|
||||||
|
Return()
|
||||||
|
|
||||||
// ensure the call was created
|
require.Equal(t, []*Call{c}, mockedService.ExpectedCalls)
|
||||||
if assert.Equal(t, 1, len(mockedService.ExpectedCalls)) {
|
|
||||||
call := mockedService.ExpectedCalls[0]
|
|
||||||
|
|
||||||
assert.Equal(t, "TheExampleMethod", call.Method)
|
call := mockedService.ExpectedCalls[0]
|
||||||
assert.Equal(t, "A", call.Arguments[0])
|
|
||||||
assert.Equal(t, "B", call.Arguments[1])
|
|
||||||
assert.Equal(t, true, call.Arguments[2])
|
|
||||||
assert.Equal(t, 0, len(call.ReturnArguments))
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
assert.Equal(t, "TheExampleMethod", call.Method)
|
||||||
|
assert.Equal(t, "A", call.Arguments[0])
|
||||||
|
assert.Equal(t, "B", call.Arguments[1])
|
||||||
|
assert.Equal(t, true, call.Arguments[2])
|
||||||
|
assert.Equal(t, 0, len(call.ReturnArguments))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Mock_findExpectedCall(t *testing.T) {
|
func Test_Mock_findExpectedCall(t *testing.T) {
|
||||||
|
|
@ -455,7 +586,7 @@ func Test_callString(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_Called(t *testing.T) {
|
func Test_Mock_Called(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("Test_Mock_Called", 1, 2, 3).Return(5, "6", true)
|
mockedService.On("Test_Mock_Called", 1, 2, 3).Return(5, "6", true)
|
||||||
|
|
||||||
|
|
@ -482,7 +613,7 @@ func asyncCall(m *Mock, ch chan Arguments) {
|
||||||
|
|
||||||
func Test_Mock_Called_blocks(t *testing.T) {
|
func Test_Mock_Called_blocks(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.Mock.On("asyncCall", 1, 2, 3).Return(5, "6", true).After(2 * time.Millisecond)
|
mockedService.Mock.On("asyncCall", 1, 2, 3).Return(5, "6", true).After(2 * time.Millisecond)
|
||||||
|
|
||||||
|
|
@ -515,10 +646,15 @@ func Test_Mock_Called_blocks(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_Called_For_Bounded_Repeatability(t *testing.T) {
|
func Test_Mock_Called_For_Bounded_Repeatability(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3).Return(5, "6", true).Once()
|
mockedService.
|
||||||
mockedService.On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3).Return(-1, "hi", false)
|
On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3).
|
||||||
|
Return(5, "6", true).
|
||||||
|
Once()
|
||||||
|
mockedService.
|
||||||
|
On("Test_Mock_Called_For_Bounded_Repeatability", 1, 2, 3).
|
||||||
|
Return(-1, "hi", false)
|
||||||
|
|
||||||
returnArguments1 := mockedService.Called(1, 2, 3)
|
returnArguments1 := mockedService.Called(1, 2, 3)
|
||||||
returnArguments2 := mockedService.Called(1, 2, 3)
|
returnArguments2 := mockedService.Called(1, 2, 3)
|
||||||
|
|
@ -551,7 +687,7 @@ func Test_Mock_Called_For_Bounded_Repeatability(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_Called_For_SetTime_Expectation(t *testing.T) {
|
func Test_Mock_Called_For_SetTime_Expectation(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("TheExampleMethod", 1, 2, 3).Return(5, "6", true).Times(4)
|
mockedService.On("TheExampleMethod", 1, 2, 3).Return(5, "6", true).Times(4)
|
||||||
|
|
||||||
|
|
@ -567,7 +703,7 @@ func Test_Mock_Called_For_SetTime_Expectation(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_Called_Unexpected(t *testing.T) {
|
func Test_Mock_Called_Unexpected(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
// make sure it panics if no expectation was made
|
// make sure it panics if no expectation was made
|
||||||
assert.Panics(t, func() {
|
assert.Panics(t, func() {
|
||||||
|
|
@ -578,9 +714,9 @@ func Test_Mock_Called_Unexpected(t *testing.T) {
|
||||||
|
|
||||||
func Test_AssertExpectationsForObjects_Helper(t *testing.T) {
|
func Test_AssertExpectationsForObjects_Helper(t *testing.T) {
|
||||||
|
|
||||||
var mockedService1 *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService1 = new(TestExampleImplementation)
|
||||||
var mockedService2 *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService2 = new(TestExampleImplementation)
|
||||||
var mockedService3 *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService3 = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService1.On("Test_AssertExpectationsForObjects_Helper", 1).Return()
|
mockedService1.On("Test_AssertExpectationsForObjects_Helper", 1).Return()
|
||||||
mockedService2.On("Test_AssertExpectationsForObjects_Helper", 2).Return()
|
mockedService2.On("Test_AssertExpectationsForObjects_Helper", 2).Return()
|
||||||
|
|
@ -596,9 +732,9 @@ func Test_AssertExpectationsForObjects_Helper(t *testing.T) {
|
||||||
|
|
||||||
func Test_AssertExpectationsForObjects_Helper_Failed(t *testing.T) {
|
func Test_AssertExpectationsForObjects_Helper_Failed(t *testing.T) {
|
||||||
|
|
||||||
var mockedService1 *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService1 = new(TestExampleImplementation)
|
||||||
var mockedService2 *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService2 = new(TestExampleImplementation)
|
||||||
var mockedService3 *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService3 = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService1.On("Test_AssertExpectationsForObjects_Helper_Failed", 1).Return()
|
mockedService1.On("Test_AssertExpectationsForObjects_Helper_Failed", 1).Return()
|
||||||
mockedService2.On("Test_AssertExpectationsForObjects_Helper_Failed", 2).Return()
|
mockedService2.On("Test_AssertExpectationsForObjects_Helper_Failed", 2).Return()
|
||||||
|
|
@ -614,7 +750,7 @@ func Test_AssertExpectationsForObjects_Helper_Failed(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_AssertExpectations(t *testing.T) {
|
func Test_Mock_AssertExpectations(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("Test_Mock_AssertExpectations", 1, 2, 3).Return(5, 6, 7)
|
mockedService.On("Test_Mock_AssertExpectations", 1, 2, 3).Return(5, 6, 7)
|
||||||
|
|
||||||
|
|
@ -631,7 +767,7 @@ func Test_Mock_AssertExpectations(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_AssertExpectationsCustomType(t *testing.T) {
|
func Test_Mock_AssertExpectationsCustomType(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).Return(nil).Once()
|
mockedService.On("TheExampleMethod3", AnythingOfType("*mock.ExampleType")).Return(nil).Once()
|
||||||
|
|
||||||
|
|
@ -648,7 +784,7 @@ func Test_Mock_AssertExpectationsCustomType(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
|
func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("Test_Mock_AssertExpectations_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Twice()
|
mockedService.On("Test_Mock_AssertExpectations_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Twice()
|
||||||
|
|
||||||
|
|
@ -669,7 +805,7 @@ func Test_Mock_AssertExpectations_With_Repeatability(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) {
|
func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 1, 2, 3).Return(5, 6, 7)
|
mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 1, 2, 3).Return(5, 6, 7)
|
||||||
mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 4, 5, 6).Return(5, 6, 7)
|
mockedService.On("Test_Mock_TwoCallsWithDifferentArguments", 4, 5, 6).Return(5, 6, 7)
|
||||||
|
|
@ -688,7 +824,7 @@ func Test_Mock_TwoCallsWithDifferentArguments(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_AssertNumberOfCalls(t *testing.T) {
|
func Test_Mock_AssertNumberOfCalls(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("Test_Mock_AssertNumberOfCalls", 1, 2, 3).Return(5, 6, 7)
|
mockedService.On("Test_Mock_AssertNumberOfCalls", 1, 2, 3).Return(5, 6, 7)
|
||||||
|
|
||||||
|
|
@ -702,7 +838,7 @@ func Test_Mock_AssertNumberOfCalls(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_AssertCalled(t *testing.T) {
|
func Test_Mock_AssertCalled(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("Test_Mock_AssertCalled", 1, 2, 3).Return(5, 6, 7)
|
mockedService.On("Test_Mock_AssertCalled", 1, 2, 3).Return(5, 6, 7)
|
||||||
|
|
||||||
|
|
@ -714,9 +850,11 @@ func Test_Mock_AssertCalled(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_AssertCalled_WithAnythingOfTypeArgument(t *testing.T) {
|
func Test_Mock_AssertCalled_WithAnythingOfTypeArgument(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("Test_Mock_AssertCalled_WithAnythingOfTypeArgument", Anything, Anything, Anything).Return()
|
mockedService.
|
||||||
|
On("Test_Mock_AssertCalled_WithAnythingOfTypeArgument", Anything, Anything, Anything).
|
||||||
|
Return()
|
||||||
|
|
||||||
mockedService.Called(1, "two", []uint8("three"))
|
mockedService.Called(1, "two", []uint8("three"))
|
||||||
|
|
||||||
|
|
@ -726,7 +864,7 @@ func Test_Mock_AssertCalled_WithAnythingOfTypeArgument(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_AssertCalled_WithArguments(t *testing.T) {
|
func Test_Mock_AssertCalled_WithArguments(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("Test_Mock_AssertCalled_WithArguments", 1, 2, 3).Return(5, 6, 7)
|
mockedService.On("Test_Mock_AssertCalled_WithArguments", 1, 2, 3).Return(5, 6, 7)
|
||||||
|
|
||||||
|
|
@ -740,7 +878,7 @@ func Test_Mock_AssertCalled_WithArguments(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_AssertCalled_WithArguments_With_Repeatability(t *testing.T) {
|
func Test_Mock_AssertCalled_WithArguments_With_Repeatability(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Once()
|
mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 1, 2, 3).Return(5, 6, 7).Once()
|
||||||
mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4).Return(5, 6, 7).Once()
|
mockedService.On("Test_Mock_AssertCalled_WithArguments_With_Repeatability", 2, 3, 4).Return(5, 6, 7).Once()
|
||||||
|
|
@ -757,7 +895,7 @@ func Test_Mock_AssertCalled_WithArguments_With_Repeatability(t *testing.T) {
|
||||||
|
|
||||||
func Test_Mock_AssertNotCalled(t *testing.T) {
|
func Test_Mock_AssertNotCalled(t *testing.T) {
|
||||||
|
|
||||||
var mockedService *TestExampleImplementation = new(TestExampleImplementation)
|
var mockedService = new(TestExampleImplementation)
|
||||||
|
|
||||||
mockedService.On("Test_Mock_AssertNotCalled", 1, 2, 3).Return(5, 6, 7)
|
mockedService.On("Test_Mock_AssertNotCalled", 1, 2, 3).Return(5, 6, 7)
|
||||||
|
|
||||||
|
|
@ -772,7 +910,7 @@ func Test_Mock_AssertNotCalled(t *testing.T) {
|
||||||
*/
|
*/
|
||||||
func Test_Arguments_Get(t *testing.T) {
|
func Test_Arguments_Get(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", 123, true}
|
var args = Arguments([]interface{}{"string", 123, true})
|
||||||
|
|
||||||
assert.Equal(t, "string", args.Get(0).(string))
|
assert.Equal(t, "string", args.Get(0).(string))
|
||||||
assert.Equal(t, 123, args.Get(1).(int))
|
assert.Equal(t, 123, args.Get(1).(int))
|
||||||
|
|
@ -782,7 +920,7 @@ func Test_Arguments_Get(t *testing.T) {
|
||||||
|
|
||||||
func Test_Arguments_Is(t *testing.T) {
|
func Test_Arguments_Is(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", 123, true}
|
var args = Arguments([]interface{}{"string", 123, true})
|
||||||
|
|
||||||
assert.True(t, args.Is("string", 123, true))
|
assert.True(t, args.Is("string", 123, true))
|
||||||
assert.False(t, args.Is("wrong", 456, false))
|
assert.False(t, args.Is("wrong", 456, false))
|
||||||
|
|
@ -791,7 +929,7 @@ func Test_Arguments_Is(t *testing.T) {
|
||||||
|
|
||||||
func Test_Arguments_Diff(t *testing.T) {
|
func Test_Arguments_Diff(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"Hello World", 123, true}
|
var args = Arguments([]interface{}{"Hello World", 123, true})
|
||||||
var diff string
|
var diff string
|
||||||
var count int
|
var count int
|
||||||
diff, count = args.Diff([]interface{}{"Hello World", 456, "false"})
|
diff, count = args.Diff([]interface{}{"Hello World", 456, "false"})
|
||||||
|
|
@ -804,7 +942,7 @@ func Test_Arguments_Diff(t *testing.T) {
|
||||||
|
|
||||||
func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) {
|
func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", 123, true}
|
var args = Arguments([]interface{}{"string", 123, true})
|
||||||
var diff string
|
var diff string
|
||||||
var count int
|
var count int
|
||||||
diff, count = args.Diff([]interface{}{"string", 456, "false", "extra"})
|
diff, count = args.Diff([]interface{}{"string", 456, "false", "extra"})
|
||||||
|
|
@ -816,7 +954,7 @@ func Test_Arguments_Diff_DifferentNumberOfArgs(t *testing.T) {
|
||||||
|
|
||||||
func Test_Arguments_Diff_WithAnythingArgument(t *testing.T) {
|
func Test_Arguments_Diff_WithAnythingArgument(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", 123, true}
|
var args = Arguments([]interface{}{"string", 123, true})
|
||||||
var count int
|
var count int
|
||||||
_, count = args.Diff([]interface{}{"string", Anything, true})
|
_, count = args.Diff([]interface{}{"string", Anything, true})
|
||||||
|
|
||||||
|
|
@ -826,7 +964,7 @@ func Test_Arguments_Diff_WithAnythingArgument(t *testing.T) {
|
||||||
|
|
||||||
func Test_Arguments_Diff_WithAnythingArgument_InActualToo(t *testing.T) {
|
func Test_Arguments_Diff_WithAnythingArgument_InActualToo(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", Anything, true}
|
var args = Arguments([]interface{}{"string", Anything, true})
|
||||||
var count int
|
var count int
|
||||||
_, count = args.Diff([]interface{}{"string", 123, true})
|
_, count = args.Diff([]interface{}{"string", 123, true})
|
||||||
|
|
||||||
|
|
@ -836,7 +974,7 @@ func Test_Arguments_Diff_WithAnythingArgument_InActualToo(t *testing.T) {
|
||||||
|
|
||||||
func Test_Arguments_Diff_WithAnythingOfTypeArgument(t *testing.T) {
|
func Test_Arguments_Diff_WithAnythingOfTypeArgument(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", AnythingOfType("int"), true}
|
var args = Arguments([]interface{}{"string", AnythingOfType("int"), true})
|
||||||
var count int
|
var count int
|
||||||
_, count = args.Diff([]interface{}{"string", 123, true})
|
_, count = args.Diff([]interface{}{"string", 123, true})
|
||||||
|
|
||||||
|
|
@ -846,7 +984,7 @@ func Test_Arguments_Diff_WithAnythingOfTypeArgument(t *testing.T) {
|
||||||
|
|
||||||
func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) {
|
func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", AnythingOfType("string"), true}
|
var args = Arguments([]interface{}{"string", AnythingOfType("string"), true})
|
||||||
var count int
|
var count int
|
||||||
var diff string
|
var diff string
|
||||||
diff, count = args.Diff([]interface{}{"string", 123, true})
|
diff, count = args.Diff([]interface{}{"string", 123, true})
|
||||||
|
|
@ -856,9 +994,31 @@ func Test_Arguments_Diff_WithAnythingOfTypeArgument_Failing(t *testing.T) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_Arguments_Diff_WithArgMatcher(t *testing.T) {
|
||||||
|
matchFn := func(a int) bool {
|
||||||
|
return a == 123
|
||||||
|
}
|
||||||
|
var args = Arguments([]interface{}{"string", MatchedBy(matchFn), true})
|
||||||
|
|
||||||
|
diff, count := args.Diff([]interface{}{"string", 124, true})
|
||||||
|
assert.Equal(t, 1, count)
|
||||||
|
assert.Contains(t, diff, `%!s(int=124) not matched by func(int) bool`)
|
||||||
|
|
||||||
|
diff, count = args.Diff([]interface{}{"string", false, true})
|
||||||
|
assert.Equal(t, 1, count)
|
||||||
|
assert.Contains(t, diff, `%!s(bool=false) not matched by func(int) bool`)
|
||||||
|
|
||||||
|
diff, count = args.Diff([]interface{}{"string", 123, false})
|
||||||
|
assert.Contains(t, diff, `%!s(int=123) matched by func(int) bool`)
|
||||||
|
|
||||||
|
diff, count = args.Diff([]interface{}{"string", 123, true})
|
||||||
|
assert.Equal(t, 0, count)
|
||||||
|
assert.Contains(t, diff, `No differences.`)
|
||||||
|
}
|
||||||
|
|
||||||
func Test_Arguments_Assert(t *testing.T) {
|
func Test_Arguments_Assert(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", 123, true}
|
var args = Arguments([]interface{}{"string", 123, true})
|
||||||
|
|
||||||
assert.True(t, args.Assert(t, "string", 123, true))
|
assert.True(t, args.Assert(t, "string", 123, true))
|
||||||
|
|
||||||
|
|
@ -866,43 +1026,43 @@ func Test_Arguments_Assert(t *testing.T) {
|
||||||
|
|
||||||
func Test_Arguments_String_Representation(t *testing.T) {
|
func Test_Arguments_String_Representation(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", 123, true}
|
var args = Arguments([]interface{}{"string", 123, true})
|
||||||
assert.Equal(t, `string,int,bool`, args.String())
|
assert.Equal(t, `string,int,bool`, args.String())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Arguments_String(t *testing.T) {
|
func Test_Arguments_String(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", 123, true}
|
var args = Arguments([]interface{}{"string", 123, true})
|
||||||
assert.Equal(t, "string", args.String(0))
|
assert.Equal(t, "string", args.String(0))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Arguments_Error(t *testing.T) {
|
func Test_Arguments_Error(t *testing.T) {
|
||||||
|
|
||||||
var err error = errors.New("An Error")
|
var err = errors.New("An Error")
|
||||||
var args Arguments = []interface{}{"string", 123, true, err}
|
var args = Arguments([]interface{}{"string", 123, true, err})
|
||||||
assert.Equal(t, err, args.Error(3))
|
assert.Equal(t, err, args.Error(3))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Arguments_Error_Nil(t *testing.T) {
|
func Test_Arguments_Error_Nil(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", 123, true, nil}
|
var args = Arguments([]interface{}{"string", 123, true, nil})
|
||||||
assert.Equal(t, nil, args.Error(3))
|
assert.Equal(t, nil, args.Error(3))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Arguments_Int(t *testing.T) {
|
func Test_Arguments_Int(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", 123, true}
|
var args = Arguments([]interface{}{"string", 123, true})
|
||||||
assert.Equal(t, 123, args.Int(1))
|
assert.Equal(t, 123, args.Int(1))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Arguments_Bool(t *testing.T) {
|
func Test_Arguments_Bool(t *testing.T) {
|
||||||
|
|
||||||
var args Arguments = []interface{}{"string", 123, true}
|
var args = Arguments([]interface{}{"string", 123, true})
|
||||||
assert.Equal(t, true, args.Bool(2))
|
assert.Equal(t, true, args.Bool(2))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue