diff --git a/Gopkg.lock b/Gopkg.lock index cf1b5ec50f..9576ee3fd2 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1219,6 +1219,14 @@ pruneopts = "UT" revision = "ae77be60afb1dcacde03767a8c37337fad28ac14" +[[projects]] + digest = "1:ca955a9cd5b50b0f43d2cc3aeb35c951473eeca41b34eb67507f1dbcc0542394" + name = "github.com/kr/pretty" + packages = ["."] + pruneopts = "UT" + revision = "73f6ac0b30a98e433b289500d779f50c1a6f0712" + version = "v0.1.0" + [[projects]] digest = "1:075fe2b22b9fcec90cecd98546c2096d73a3ab9458261f5647512fba3e0420eb" name = "github.com/kr/pty" @@ -1227,6 +1235,14 @@ revision = "2c10821df3c3cf905230d078702dfbe9404c9b23" version = "v1.0.0" +[[projects]] + digest = "1:15b5cc79aad436d47019f814fde81a10221c740dc8ddf769221a65097fb6c2e9" + name = "github.com/kr/text" + packages = ["."] + pruneopts = "UT" + revision = "e2ffdb16a802fe2bb95e2e35ff34f0e53aeef34f" + version = "v0.1.0" + [[projects]] digest = "1:7a20d4221f44dadcdfe5a510725d3f26185a7ac680c207755f73963473337e44" name = "github.com/kylelemons/godebug" @@ -1972,11 +1988,12 @@ source = "github.com/gravitational/kingpin" [[projects]] - digest = "1:a59b147b633c9b4f5f0eba6ddc282810fec9c592c41fc3e6c1fef74af01705dc" + branch = "v1" + digest = "1:af715ae33cc1f5695c4b2a4e4b21d008add8802a99e15bb467ac7c32edb5000d" name = "gopkg.in/check.v1" packages = ["."] pruneopts = "UT" - revision = "64131543e7896d5bcc6bd5a76287eb75ea96c673" + revision = "788fd78401277ebd861206a03c884797c6ec5541" [[projects]] digest = "1:ef72505cf098abdd34efeea032103377bec06abb61d8a06f002d5d296a4b1185" diff --git a/Gopkg.toml b/Gopkg.toml index 149ab3034b..30ff1bc64d 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -271,3 +271,8 @@ ignored = [ [[constraint]] name = "github.com/gizak/termui" version = "=v2.3.0" + +[[constraint]] + name = "gopkg.in/check.v1" + branch = "v1" + diff --git a/build.assets/Makefile b/build.assets/Makefile index e8b367350d..4f9fa993ea 100644 --- a/build.assets/Makefile +++ b/build.assets/Makefile @@ -80,6 +80,9 @@ RELEASE_OUT := $(GRAVITY_BUILDDIR)/$(RELEASE_TARBALL_NAME) BASH ?= /bin/bash +# packages to test +TEST_PACKAGES ?= $(GRAVITY_PKG_PATH)/lib/... $(GRAVITY_PKG_PATH)/tool/... + # Export variables for recursive make invocations export GRAVITY_PKG_PATH @@ -102,13 +105,14 @@ test: buildbox test-etcd docker run --net=host --rm=true $(NOROOT) \ -v $(TOP):$(SRCDIR) \ -e "GRAVITY_PKG_PATH=$(GRAVITY_PKG_PATH)" \ + -e "TEST_PACKAGES=$(TEST_PACKAGES)" \ -t $(BBOX) \ dumb-init make -C $(SRCDIR)/build.assets FLAGS='-cover -race' TEST_ETCD=true TEST_K8S=$(TEST_K8S) test-inside-container .PHONY: test-inside-container test-inside-container: - TEST_ETCD=$(TEST_ETCD) TEST_ETCD_CONFIG=$(TEST_ETCD_CONFIG) TEST_K8S=$(TEST_K8S) go test $(GRAVITY_PKG_PATH)/lib/... $(FLAGS) + TEST_ETCD=$(TEST_ETCD) TEST_ETCD_CONFIG=$(TEST_ETCD_CONFIG) TEST_K8S=$(TEST_K8S) go test $(TEST_PACKAGES) $(FLAGS) # TODO: It turns out "go vet" never really worked because we used incorrect package path # and now that I've fixed it, it produces a gazillion of warnings. So I'm commenting this # out for the time being, should uncomment once we've fixed the warnings. diff --git a/e b/e index c078d35e98..5951ad6fac 160000 --- a/e +++ b/e @@ -1 +1 @@ -Subproject commit c078d35e9811b52fe4ccbb81963cd26b377a369e +Subproject commit 5951ad6facf2bf44e41d356044e3b32a5aa393b4 diff --git a/lib/app/service/pull_test.go b/lib/app/service/pull_test.go index 5be5e7e413..926a1b9bb8 100644 --- a/lib/app/service/pull_test.go +++ b/lib/app/service/pull_test.go @@ -120,7 +120,7 @@ dependencies: - example.com/new:0.0.2 - example.com/existing:0.0.1 ` - apptest.CreateDummyApplication2(s.srcApp, locator, dependencies, c) + apptest.CreateDummyApplicationWithDependencies(s.srcApp, locator, dependencies, c) pulled, err := PullApp(AppPullRequest{ SrcPack: s.srcPack, diff --git a/lib/app/service/resources_test.go b/lib/app/service/resources_test.go index 82548dde93..177a27f9dd 100644 --- a/lib/app/service/resources_test.go +++ b/lib/app/service/resources_test.go @@ -30,7 +30,7 @@ func (r *ResourceSuite) TestTranslatesResources(c *C) { runtimePackage := loc.MustParseLocator("gravitational.io/planet:0.0.1") apptest.CreatePackage(r.pack, runtimePackage, nil, c) apptest.CreateRuntimeApplication(r.apps, c) - apptest.CreateDummyApplication(r.apps, appPackage, c) + apptest.CreateDummyApplication(appPackage, c, r.apps) _, reader, err := r.pack.ReadPackage(appPackage) c.Assert(err, IsNil) diff --git a/lib/app/service/test/builder.go b/lib/app/service/test/builder.go index 397ebb2fdc..ecc3e50065 100644 --- a/lib/app/service/test/builder.go +++ b/lib/app/service/test/builder.go @@ -43,17 +43,23 @@ func CreateDummyPackageWithContents(locator loc.Locator, items []*archive.Item, data := CreatePackageData(items, c) err := packages.UpsertRepository(locator.Repository, time.Time{}) c.Assert(err, IsNil) - _, err = packages.CreatePackage(locator, data) + _, err = packages.CreatePackage(locator, &data) c.Assert(err, IsNil) } -// CreateDummyApplication creates app with valid app manifest, but fake content -func CreateDummyApplication(apps app.Applications, loc loc.Locator, c *C) *app.Application { - return createApp(loc, "", apps, c) +// CreateDummyApplication creates app with valid app manifest, but fake content. +// It returns the application created in the last service specified with services +func CreateDummyApplication(locator loc.Locator, c *C, services ...app.Applications) (app *app.Application) { + data := createAppData(locator, "", c) + for _, service := range services { + app = CreateApplicationFromBinaryData(service, locator, data, c) + } + return app } -// CreateDummyApplication2 creates a test application with a valid manifest and specified dependencies -func CreateDummyApplication2(apps app.Applications, loc loc.Locator, dependencies string, c *C) *app.Application { +// CreateDummyApplicationWithDependencies creates a test application with a valid manifest +// and specified dependencies +func CreateDummyApplicationWithDependencies(apps app.Applications, loc loc.Locator, dependencies string, c *C) *app.Application { return createApp(loc, dependencies, apps, c) } @@ -99,6 +105,11 @@ func CreateAppWithDeps(apps app.Applications, packages pack.PackageService, c *C } func createApp(loc loc.Locator, dependencies string, apps app.Applications, c *C) *app.Application { + data := createAppData(loc, dependencies, c) + return CreateApplicationFromBinaryData(apps, loc, data, c) +} + +func createAppData(loc loc.Locator, dependencies string, c *C) bytes.Buffer { const manifestTemplate = ` apiVersion: bundle.gravitational.io/v2 kind: Bundle @@ -170,8 +181,7 @@ spec: archive.DirItem("registry/docker"), archive.ItemFromString("registry/docker/TODO", ""), } - - return CreateApplicationFromData(apps, loc, files, c) + return CreatePackageData(files, c) } func CreateApplication(apps app.Applications, locator loc.Locator, files []*archive.Item, c *C) *app.Application { @@ -180,9 +190,12 @@ func CreateApplication(apps app.Applications, locator loc.Locator, files []*arch func CreateApplicationFromData(apps app.Applications, locator loc.Locator, files []*archive.Item, c *C) *app.Application { data := CreatePackageData(files, c) + return CreateApplicationFromBinaryData(apps, locator, data, c) +} +func CreateApplicationFromBinaryData(apps app.Applications, locator loc.Locator, data bytes.Buffer, c *C) *app.Application { var labels map[string]string - app, err := apps.CreateApp(locator, data, labels) + app, err := apps.CreateApp(locator, &data, labels) c.Assert(err, IsNil) c.Assert(app, NotNil) @@ -218,7 +231,7 @@ func CreatePackage(packages pack.PackageService, locator loc.Locator, files []*a c.Assert(packages.UpsertRepository(locator.Repository, time.Time{}), IsNil) - app, err := packages.CreatePackage(locator, input) + app, err := packages.CreatePackage(locator, &input) c.Assert(err, IsNil) c.Assert(app, NotNil) @@ -230,9 +243,9 @@ func CreatePackage(packages pack.PackageService, locator loc.Locator, files []*a return envelope } -func CreatePackageData(items []*archive.Item, c *C) *bytes.Buffer { - buf := &bytes.Buffer{} - archive := archive.NewTarAppender(buf) +func CreatePackageData(items []*archive.Item, c *C) bytes.Buffer { + var buf bytes.Buffer + archive := archive.NewTarAppender(&buf) c.Assert(archive.Add(items...), IsNil) archive.Close() diff --git a/lib/app/suite/suite.go b/lib/app/suite/suite.go index 8c9157f89c..251e25f138 100644 --- a/lib/app/suite/suite.go +++ b/lib/app/suite/suite.go @@ -95,7 +95,7 @@ func (r *AppsSuite) ValidatesManifest(c *C) { errorc := make(chan error, 1) progressc := make(chan *app.ProgressEntry) op, err := apps.CreateImportOperation(&app.ImportRequest{ - Source: ioutil.NopCloser(input), + Source: ioutil.NopCloser(&input), Repository: "example.com", PackageName: "app", PackageVersion: "0.0.1", @@ -223,7 +223,7 @@ spec: errorc := make(chan error, 1) progressc := make(chan *app.ProgressEntry) op, err := apps.CreateImportOperation(&app.ImportRequest{ - Source: ioutil.NopCloser(f), + Source: ioutil.NopCloser(&f), Repository: "invalid---", // specify invalid name intentionally so import fails PackageName: "app", PackageVersion: "0.0.1", @@ -387,7 +387,7 @@ metadata: data := apptest.CreatePackageData(items, c) var labels map[string]string - app, err := apps.CreateAppWithManifest(locator, []byte(manifest), ioutil.NopCloser(data), labels) + app, err := apps.CreateAppWithManifest(locator, []byte(manifest), ioutil.NopCloser(&data), labels) c.Assert(err, IsNil) c.Assert(app, NotNil) @@ -403,14 +403,14 @@ func (r *AppsSuite) CreatesApplication(c *C) { apps := r.NewService(c, nil, nil) apptest.CreateRuntimeApplication(apps, c) app := loc.MustParseLocator("example.com/example-app:0.0.1") - apptest.CreateDummyApplication(apps, app, c) + apptest.CreateDummyApplication(app, c, apps) } func (r *AppsSuite) DeletesApplication(c *C) { apps := r.NewService(c, nil, nil) apptest.CreateRuntimeApplication(apps, c) loc := loc.MustParseLocator("example.com/example-app:0.0.1") - application := apptest.CreateDummyApplication(apps, loc, c) + application := apptest.CreateDummyApplication(loc, c, apps) c.Assert(apps.DeleteApp(app.DeleteRequest{Package: application.Package}), IsNil) @@ -569,7 +569,7 @@ metadata: data := apptest.CreatePackageData(items, c) var labels map[string]string - application, err := apps.CreateAppWithManifest(locator, manifestBytes, ioutil.NopCloser(data), labels) + application, err := apps.CreateAppWithManifest(locator, manifestBytes, ioutil.NopCloser(&data), labels) c.Assert(err, IsNil) c.Assert(application, NotNil) @@ -771,7 +771,8 @@ func (r *AppsSuite) importApplicationWithResources(apps app.Applications, vendor } service.PostProcessManifest(manifest) - input := ioutil.NopCloser(apptest.CreatePackageData(resources, c)) + buf := apptest.CreatePackageData(resources, c) + input := ioutil.NopCloser(&buf) errorc := make(chan error, 1) progressc := make(chan *app.ProgressEntry) diff --git a/lib/blob/fs/fs.go b/lib/blob/fs/fs.go index cf3cc256d5..a8b6c8385b 100644 --- a/lib/blob/fs/fs.go +++ b/lib/blob/fs/fs.go @@ -28,8 +28,8 @@ import ( "github.com/gravitational/gravity/lib/blob" "github.com/gravitational/gravity/lib/defaults" - log "github.com/sirupsen/logrus" "github.com/gravitational/trace" + log "github.com/sirupsen/logrus" ) func New(path string) (blob.Objects, error) { diff --git a/tool/gravity/cli/utils.go b/tool/gravity/cli/utils.go index c256f7ca95..129670db90 100644 --- a/tool/gravity/cli/utils.go +++ b/tool/gravity/cli/utils.go @@ -308,7 +308,7 @@ func updateCommandWithFlags(command []string, parser ArgsParser, flagsToAdd []fl for _, el := range ctx.Elements { switch c := el.Clause.(type) { case *kingpin.ArgClause: - args = append(args, strconv.Quote(c.Model().Name)) + args = append(args, strconv.Quote(*el.Value)) case *kingpin.FlagClause: if _, ok := c.Model().Value.(boolFlag); ok { args = append(args, fmt.Sprint("--", c.Model().Name)) diff --git a/tool/gravity/cli/utils_test.go b/tool/gravity/cli/utils_test.go index c3013aa142..bc3875689d 100644 --- a/tool/gravity/cli/utils_test.go +++ b/tool/gravity/cli/utils_test.go @@ -56,14 +56,14 @@ func (*S) TestUpdatesCommandLine(c *check.C) { }, { comment: "Quotes flags and args", - inputArgs: []string{"install", `--token=some token`, "appdir"}, + inputArgs: []string{"install", `--token=some token`, "/path/to/data"}, flags: []flag{ { name: "advertise-addr", value: "localhost:8080", }, }, outputArgs: []string{ - "install", "--token", `"some token"`, `"appdir"`, "--advertise-addr", `"localhost:8080"`, + "install", "--token", `"some token"`, `"/path/to/data"`, "--advertise-addr", `"localhost:8080"`, }, }, } diff --git a/vendor/github.com/kr/pretty/.gitignore b/vendor/github.com/kr/pretty/.gitignore new file mode 100644 index 0000000000..1f0a99f2f2 --- /dev/null +++ b/vendor/github.com/kr/pretty/.gitignore @@ -0,0 +1,4 @@ +[568].out +_go* +_test* +_obj diff --git a/vendor/github.com/kr/pretty/License b/vendor/github.com/kr/pretty/License new file mode 100644 index 0000000000..05c783ccf6 --- /dev/null +++ b/vendor/github.com/kr/pretty/License @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright 2012 Keith Rarick + +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. diff --git a/vendor/github.com/kr/pretty/Readme b/vendor/github.com/kr/pretty/Readme new file mode 100644 index 0000000000..c589fc622b --- /dev/null +++ b/vendor/github.com/kr/pretty/Readme @@ -0,0 +1,9 @@ +package pretty + + import "github.com/kr/pretty" + + Package pretty provides pretty-printing for Go values. + +Documentation + + http://godoc.org/github.com/kr/pretty diff --git a/vendor/github.com/kr/pretty/diff.go b/vendor/github.com/kr/pretty/diff.go new file mode 100644 index 0000000000..6aa7f743a2 --- /dev/null +++ b/vendor/github.com/kr/pretty/diff.go @@ -0,0 +1,265 @@ +package pretty + +import ( + "fmt" + "io" + "reflect" +) + +type sbuf []string + +func (p *sbuf) Printf(format string, a ...interface{}) { + s := fmt.Sprintf(format, a...) + *p = append(*p, s) +} + +// Diff returns a slice where each element describes +// a difference between a and b. +func Diff(a, b interface{}) (desc []string) { + Pdiff((*sbuf)(&desc), a, b) + return desc +} + +// wprintfer calls Fprintf on w for each Printf call +// with a trailing newline. +type wprintfer struct{ w io.Writer } + +func (p *wprintfer) Printf(format string, a ...interface{}) { + fmt.Fprintf(p.w, format+"\n", a...) +} + +// Fdiff writes to w a description of the differences between a and b. +func Fdiff(w io.Writer, a, b interface{}) { + Pdiff(&wprintfer{w}, a, b) +} + +type Printfer interface { + Printf(format string, a ...interface{}) +} + +// Pdiff prints to p a description of the differences between a and b. +// It calls Printf once for each difference, with no trailing newline. +// The standard library log.Logger is a Printfer. +func Pdiff(p Printfer, a, b interface{}) { + diffPrinter{w: p}.diff(reflect.ValueOf(a), reflect.ValueOf(b)) +} + +type Logfer interface { + Logf(format string, a ...interface{}) +} + +// logprintfer calls Fprintf on w for each Printf call +// with a trailing newline. +type logprintfer struct{ l Logfer } + +func (p *logprintfer) Printf(format string, a ...interface{}) { + p.l.Logf(format, a...) +} + +// Ldiff prints to l a description of the differences between a and b. +// It calls Logf once for each difference, with no trailing newline. +// The standard library testing.T and testing.B are Logfers. +func Ldiff(l Logfer, a, b interface{}) { + Pdiff(&logprintfer{l}, a, b) +} + +type diffPrinter struct { + w Printfer + l string // label +} + +func (w diffPrinter) printf(f string, a ...interface{}) { + var l string + if w.l != "" { + l = w.l + ": " + } + w.w.Printf(l+f, a...) +} + +func (w diffPrinter) diff(av, bv reflect.Value) { + if !av.IsValid() && bv.IsValid() { + w.printf("nil != %# v", formatter{v: bv, quote: true}) + return + } + if av.IsValid() && !bv.IsValid() { + w.printf("%# v != nil", formatter{v: av, quote: true}) + return + } + if !av.IsValid() && !bv.IsValid() { + return + } + + at := av.Type() + bt := bv.Type() + if at != bt { + w.printf("%v != %v", at, bt) + return + } + + switch kind := at.Kind(); kind { + case reflect.Bool: + if a, b := av.Bool(), bv.Bool(); a != b { + w.printf("%v != %v", a, b) + } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if a, b := av.Int(), bv.Int(); a != b { + w.printf("%d != %d", a, b) + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + if a, b := av.Uint(), bv.Uint(); a != b { + w.printf("%d != %d", a, b) + } + case reflect.Float32, reflect.Float64: + if a, b := av.Float(), bv.Float(); a != b { + w.printf("%v != %v", a, b) + } + case reflect.Complex64, reflect.Complex128: + if a, b := av.Complex(), bv.Complex(); a != b { + w.printf("%v != %v", a, b) + } + case reflect.Array: + n := av.Len() + for i := 0; i < n; i++ { + w.relabel(fmt.Sprintf("[%d]", i)).diff(av.Index(i), bv.Index(i)) + } + case reflect.Chan, reflect.Func, reflect.UnsafePointer: + if a, b := av.Pointer(), bv.Pointer(); a != b { + w.printf("%#x != %#x", a, b) + } + case reflect.Interface: + w.diff(av.Elem(), bv.Elem()) + case reflect.Map: + ak, both, bk := keyDiff(av.MapKeys(), bv.MapKeys()) + for _, k := range ak { + w := w.relabel(fmt.Sprintf("[%#v]", k)) + w.printf("%q != (missing)", av.MapIndex(k)) + } + for _, k := range both { + w := w.relabel(fmt.Sprintf("[%#v]", k)) + w.diff(av.MapIndex(k), bv.MapIndex(k)) + } + for _, k := range bk { + w := w.relabel(fmt.Sprintf("[%#v]", k)) + w.printf("(missing) != %q", bv.MapIndex(k)) + } + case reflect.Ptr: + switch { + case av.IsNil() && !bv.IsNil(): + w.printf("nil != %# v", formatter{v: bv, quote: true}) + case !av.IsNil() && bv.IsNil(): + w.printf("%# v != nil", formatter{v: av, quote: true}) + case !av.IsNil() && !bv.IsNil(): + w.diff(av.Elem(), bv.Elem()) + } + case reflect.Slice: + lenA := av.Len() + lenB := bv.Len() + if lenA != lenB { + w.printf("%s[%d] != %s[%d]", av.Type(), lenA, bv.Type(), lenB) + break + } + for i := 0; i < lenA; i++ { + w.relabel(fmt.Sprintf("[%d]", i)).diff(av.Index(i), bv.Index(i)) + } + case reflect.String: + if a, b := av.String(), bv.String(); a != b { + w.printf("%q != %q", a, b) + } + case reflect.Struct: + for i := 0; i < av.NumField(); i++ { + w.relabel(at.Field(i).Name).diff(av.Field(i), bv.Field(i)) + } + default: + panic("unknown reflect Kind: " + kind.String()) + } +} + +func (d diffPrinter) relabel(name string) (d1 diffPrinter) { + d1 = d + if d.l != "" && name[0] != '[' { + d1.l += "." + } + d1.l += name + return d1 +} + +// keyEqual compares a and b for equality. +// Both a and b must be valid map keys. +func keyEqual(av, bv reflect.Value) bool { + if !av.IsValid() && !bv.IsValid() { + return true + } + if !av.IsValid() || !bv.IsValid() || av.Type() != bv.Type() { + return false + } + switch kind := av.Kind(); kind { + case reflect.Bool: + a, b := av.Bool(), bv.Bool() + return a == b + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + a, b := av.Int(), bv.Int() + return a == b + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + a, b := av.Uint(), bv.Uint() + return a == b + case reflect.Float32, reflect.Float64: + a, b := av.Float(), bv.Float() + return a == b + case reflect.Complex64, reflect.Complex128: + a, b := av.Complex(), bv.Complex() + return a == b + case reflect.Array: + for i := 0; i < av.Len(); i++ { + if !keyEqual(av.Index(i), bv.Index(i)) { + return false + } + } + return true + case reflect.Chan, reflect.UnsafePointer, reflect.Ptr: + a, b := av.Pointer(), bv.Pointer() + return a == b + case reflect.Interface: + return keyEqual(av.Elem(), bv.Elem()) + case reflect.String: + a, b := av.String(), bv.String() + return a == b + case reflect.Struct: + for i := 0; i < av.NumField(); i++ { + if !keyEqual(av.Field(i), bv.Field(i)) { + return false + } + } + return true + default: + panic("invalid map key type " + av.Type().String()) + } +} + +func keyDiff(a, b []reflect.Value) (ak, both, bk []reflect.Value) { + for _, av := range a { + inBoth := false + for _, bv := range b { + if keyEqual(av, bv) { + inBoth = true + both = append(both, av) + break + } + } + if !inBoth { + ak = append(ak, av) + } + } + for _, bv := range b { + inBoth := false + for _, av := range a { + if keyEqual(av, bv) { + inBoth = true + break + } + } + if !inBoth { + bk = append(bk, bv) + } + } + return +} diff --git a/vendor/github.com/kr/pretty/formatter.go b/vendor/github.com/kr/pretty/formatter.go new file mode 100644 index 0000000000..a317d7b8ee --- /dev/null +++ b/vendor/github.com/kr/pretty/formatter.go @@ -0,0 +1,328 @@ +package pretty + +import ( + "fmt" + "io" + "reflect" + "strconv" + "text/tabwriter" + + "github.com/kr/text" +) + +type formatter struct { + v reflect.Value + force bool + quote bool +} + +// Formatter makes a wrapper, f, that will format x as go source with line +// breaks and tabs. Object f responds to the "%v" formatting verb when both the +// "#" and " " (space) flags are set, for example: +// +// fmt.Sprintf("%# v", Formatter(x)) +// +// If one of these two flags is not set, or any other verb is used, f will +// format x according to the usual rules of package fmt. +// In particular, if x satisfies fmt.Formatter, then x.Format will be called. +func Formatter(x interface{}) (f fmt.Formatter) { + return formatter{v: reflect.ValueOf(x), quote: true} +} + +func (fo formatter) String() string { + return fmt.Sprint(fo.v.Interface()) // unwrap it +} + +func (fo formatter) passThrough(f fmt.State, c rune) { + s := "%" + for i := 0; i < 128; i++ { + if f.Flag(i) { + s += string(i) + } + } + if w, ok := f.Width(); ok { + s += fmt.Sprintf("%d", w) + } + if p, ok := f.Precision(); ok { + s += fmt.Sprintf(".%d", p) + } + s += string(c) + fmt.Fprintf(f, s, fo.v.Interface()) +} + +func (fo formatter) Format(f fmt.State, c rune) { + if fo.force || c == 'v' && f.Flag('#') && f.Flag(' ') { + w := tabwriter.NewWriter(f, 4, 4, 1, ' ', 0) + p := &printer{tw: w, Writer: w, visited: make(map[visit]int)} + p.printValue(fo.v, true, fo.quote) + w.Flush() + return + } + fo.passThrough(f, c) +} + +type printer struct { + io.Writer + tw *tabwriter.Writer + visited map[visit]int + depth int +} + +func (p *printer) indent() *printer { + q := *p + q.tw = tabwriter.NewWriter(p.Writer, 4, 4, 1, ' ', 0) + q.Writer = text.NewIndentWriter(q.tw, []byte{'\t'}) + return &q +} + +func (p *printer) printInline(v reflect.Value, x interface{}, showType bool) { + if showType { + io.WriteString(p, v.Type().String()) + fmt.Fprintf(p, "(%#v)", x) + } else { + fmt.Fprintf(p, "%#v", x) + } +} + +// printValue must keep track of already-printed pointer values to avoid +// infinite recursion. +type visit struct { + v uintptr + typ reflect.Type +} + +func (p *printer) printValue(v reflect.Value, showType, quote bool) { + if p.depth > 10 { + io.WriteString(p, "!%v(DEPTH EXCEEDED)") + return + } + + switch v.Kind() { + case reflect.Bool: + p.printInline(v, v.Bool(), showType) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + p.printInline(v, v.Int(), showType) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + p.printInline(v, v.Uint(), showType) + case reflect.Float32, reflect.Float64: + p.printInline(v, v.Float(), showType) + case reflect.Complex64, reflect.Complex128: + fmt.Fprintf(p, "%#v", v.Complex()) + case reflect.String: + p.fmtString(v.String(), quote) + case reflect.Map: + t := v.Type() + if showType { + io.WriteString(p, t.String()) + } + writeByte(p, '{') + if nonzero(v) { + expand := !canInline(v.Type()) + pp := p + if expand { + writeByte(p, '\n') + pp = p.indent() + } + keys := v.MapKeys() + for i := 0; i < v.Len(); i++ { + showTypeInStruct := true + k := keys[i] + mv := v.MapIndex(k) + pp.printValue(k, false, true) + writeByte(pp, ':') + if expand { + writeByte(pp, '\t') + } + showTypeInStruct = t.Elem().Kind() == reflect.Interface + pp.printValue(mv, showTypeInStruct, true) + if expand { + io.WriteString(pp, ",\n") + } else if i < v.Len()-1 { + io.WriteString(pp, ", ") + } + } + if expand { + pp.tw.Flush() + } + } + writeByte(p, '}') + case reflect.Struct: + t := v.Type() + if v.CanAddr() { + addr := v.UnsafeAddr() + vis := visit{addr, t} + if vd, ok := p.visited[vis]; ok && vd < p.depth { + p.fmtString(t.String()+"{(CYCLIC REFERENCE)}", false) + break // don't print v again + } + p.visited[vis] = p.depth + } + + if showType { + io.WriteString(p, t.String()) + } + writeByte(p, '{') + if nonzero(v) { + expand := !canInline(v.Type()) + pp := p + if expand { + writeByte(p, '\n') + pp = p.indent() + } + for i := 0; i < v.NumField(); i++ { + showTypeInStruct := true + if f := t.Field(i); f.Name != "" { + io.WriteString(pp, f.Name) + writeByte(pp, ':') + if expand { + writeByte(pp, '\t') + } + showTypeInStruct = labelType(f.Type) + } + pp.printValue(getField(v, i), showTypeInStruct, true) + if expand { + io.WriteString(pp, ",\n") + } else if i < v.NumField()-1 { + io.WriteString(pp, ", ") + } + } + if expand { + pp.tw.Flush() + } + } + writeByte(p, '}') + case reflect.Interface: + switch e := v.Elem(); { + case e.Kind() == reflect.Invalid: + io.WriteString(p, "nil") + case e.IsValid(): + pp := *p + pp.depth++ + pp.printValue(e, showType, true) + default: + io.WriteString(p, v.Type().String()) + io.WriteString(p, "(nil)") + } + case reflect.Array, reflect.Slice: + t := v.Type() + if showType { + io.WriteString(p, t.String()) + } + if v.Kind() == reflect.Slice && v.IsNil() && showType { + io.WriteString(p, "(nil)") + break + } + if v.Kind() == reflect.Slice && v.IsNil() { + io.WriteString(p, "nil") + break + } + writeByte(p, '{') + expand := !canInline(v.Type()) + pp := p + if expand { + writeByte(p, '\n') + pp = p.indent() + } + for i := 0; i < v.Len(); i++ { + showTypeInSlice := t.Elem().Kind() == reflect.Interface + pp.printValue(v.Index(i), showTypeInSlice, true) + if expand { + io.WriteString(pp, ",\n") + } else if i < v.Len()-1 { + io.WriteString(pp, ", ") + } + } + if expand { + pp.tw.Flush() + } + writeByte(p, '}') + case reflect.Ptr: + e := v.Elem() + if !e.IsValid() { + writeByte(p, '(') + io.WriteString(p, v.Type().String()) + io.WriteString(p, ")(nil)") + } else { + pp := *p + pp.depth++ + writeByte(pp, '&') + pp.printValue(e, true, true) + } + case reflect.Chan: + x := v.Pointer() + if showType { + writeByte(p, '(') + io.WriteString(p, v.Type().String()) + fmt.Fprintf(p, ")(%#v)", x) + } else { + fmt.Fprintf(p, "%#v", x) + } + case reflect.Func: + io.WriteString(p, v.Type().String()) + io.WriteString(p, " {...}") + case reflect.UnsafePointer: + p.printInline(v, v.Pointer(), showType) + case reflect.Invalid: + io.WriteString(p, "nil") + } +} + +func canInline(t reflect.Type) bool { + switch t.Kind() { + case reflect.Map: + return !canExpand(t.Elem()) + case reflect.Struct: + for i := 0; i < t.NumField(); i++ { + if canExpand(t.Field(i).Type) { + return false + } + } + return true + case reflect.Interface: + return false + case reflect.Array, reflect.Slice: + return !canExpand(t.Elem()) + case reflect.Ptr: + return false + case reflect.Chan, reflect.Func, reflect.UnsafePointer: + return false + } + return true +} + +func canExpand(t reflect.Type) bool { + switch t.Kind() { + case reflect.Map, reflect.Struct, + reflect.Interface, reflect.Array, reflect.Slice, + reflect.Ptr: + return true + } + return false +} + +func labelType(t reflect.Type) bool { + switch t.Kind() { + case reflect.Interface, reflect.Struct: + return true + } + return false +} + +func (p *printer) fmtString(s string, quote bool) { + if quote { + s = strconv.Quote(s) + } + io.WriteString(p, s) +} + +func writeByte(w io.Writer, b byte) { + w.Write([]byte{b}) +} + +func getField(v reflect.Value, i int) reflect.Value { + val := v.Field(i) + if val.Kind() == reflect.Interface && !val.IsNil() { + val = val.Elem() + } + return val +} diff --git a/vendor/github.com/kr/pretty/go.mod b/vendor/github.com/kr/pretty/go.mod new file mode 100644 index 0000000000..1e29533143 --- /dev/null +++ b/vendor/github.com/kr/pretty/go.mod @@ -0,0 +1,3 @@ +module "github.com/kr/pretty" + +require "github.com/kr/text" v0.1.0 diff --git a/vendor/github.com/kr/pretty/pretty.go b/vendor/github.com/kr/pretty/pretty.go new file mode 100644 index 0000000000..49423ec7f5 --- /dev/null +++ b/vendor/github.com/kr/pretty/pretty.go @@ -0,0 +1,108 @@ +// Package pretty provides pretty-printing for Go values. This is +// useful during debugging, to avoid wrapping long output lines in +// the terminal. +// +// It provides a function, Formatter, that can be used with any +// function that accepts a format string. It also provides +// convenience wrappers for functions in packages fmt and log. +package pretty + +import ( + "fmt" + "io" + "log" + "reflect" +) + +// Errorf is a convenience wrapper for fmt.Errorf. +// +// Calling Errorf(f, x, y) is equivalent to +// fmt.Errorf(f, Formatter(x), Formatter(y)). +func Errorf(format string, a ...interface{}) error { + return fmt.Errorf(format, wrap(a, false)...) +} + +// Fprintf is a convenience wrapper for fmt.Fprintf. +// +// Calling Fprintf(w, f, x, y) is equivalent to +// fmt.Fprintf(w, f, Formatter(x), Formatter(y)). +func Fprintf(w io.Writer, format string, a ...interface{}) (n int, error error) { + return fmt.Fprintf(w, format, wrap(a, false)...) +} + +// Log is a convenience wrapper for log.Printf. +// +// Calling Log(x, y) is equivalent to +// log.Print(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Log(a ...interface{}) { + log.Print(wrap(a, true)...) +} + +// Logf is a convenience wrapper for log.Printf. +// +// Calling Logf(f, x, y) is equivalent to +// log.Printf(f, Formatter(x), Formatter(y)). +func Logf(format string, a ...interface{}) { + log.Printf(format, wrap(a, false)...) +} + +// Logln is a convenience wrapper for log.Printf. +// +// Calling Logln(x, y) is equivalent to +// log.Println(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Logln(a ...interface{}) { + log.Println(wrap(a, true)...) +} + +// Print pretty-prints its operands and writes to standard output. +// +// Calling Print(x, y) is equivalent to +// fmt.Print(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Print(a ...interface{}) (n int, errno error) { + return fmt.Print(wrap(a, true)...) +} + +// Printf is a convenience wrapper for fmt.Printf. +// +// Calling Printf(f, x, y) is equivalent to +// fmt.Printf(f, Formatter(x), Formatter(y)). +func Printf(format string, a ...interface{}) (n int, errno error) { + return fmt.Printf(format, wrap(a, false)...) +} + +// Println pretty-prints its operands and writes to standard output. +// +// Calling Print(x, y) is equivalent to +// fmt.Println(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Println(a ...interface{}) (n int, errno error) { + return fmt.Println(wrap(a, true)...) +} + +// Sprint is a convenience wrapper for fmt.Sprintf. +// +// Calling Sprint(x, y) is equivalent to +// fmt.Sprint(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Sprint(a ...interface{}) string { + return fmt.Sprint(wrap(a, true)...) +} + +// Sprintf is a convenience wrapper for fmt.Sprintf. +// +// Calling Sprintf(f, x, y) is equivalent to +// fmt.Sprintf(f, Formatter(x), Formatter(y)). +func Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, wrap(a, false)...) +} + +func wrap(a []interface{}, force bool) []interface{} { + w := make([]interface{}, len(a)) + for i, x := range a { + w[i] = formatter{v: reflect.ValueOf(x), force: force} + } + return w +} diff --git a/vendor/github.com/kr/pretty/zero.go b/vendor/github.com/kr/pretty/zero.go new file mode 100644 index 0000000000..abb5b6fc14 --- /dev/null +++ b/vendor/github.com/kr/pretty/zero.go @@ -0,0 +1,41 @@ +package pretty + +import ( + "reflect" +) + +func nonzero(v reflect.Value) bool { + switch v.Kind() { + case reflect.Bool: + return v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() != 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() != 0 + case reflect.Float32, reflect.Float64: + return v.Float() != 0 + case reflect.Complex64, reflect.Complex128: + return v.Complex() != complex(0, 0) + case reflect.String: + return v.String() != "" + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + if nonzero(getField(v, i)) { + return true + } + } + return false + case reflect.Array: + for i := 0; i < v.Len(); i++ { + if nonzero(v.Index(i)) { + return true + } + } + return false + case reflect.Map, reflect.Interface, reflect.Slice, reflect.Ptr, reflect.Chan, reflect.Func: + return !v.IsNil() + case reflect.UnsafePointer: + return v.Pointer() != 0 + } + return true +} diff --git a/vendor/github.com/kr/text/License b/vendor/github.com/kr/text/License new file mode 100644 index 0000000000..480a328059 --- /dev/null +++ b/vendor/github.com/kr/text/License @@ -0,0 +1,19 @@ +Copyright 2012 Keith Rarick + +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. diff --git a/vendor/github.com/kr/text/Readme b/vendor/github.com/kr/text/Readme new file mode 100644 index 0000000000..7e6e7c0687 --- /dev/null +++ b/vendor/github.com/kr/text/Readme @@ -0,0 +1,3 @@ +This is a Go package for manipulating paragraphs of text. + +See http://go.pkgdoc.org/github.com/kr/text for full documentation. diff --git a/vendor/github.com/kr/text/doc.go b/vendor/github.com/kr/text/doc.go new file mode 100644 index 0000000000..cf4c198f95 --- /dev/null +++ b/vendor/github.com/kr/text/doc.go @@ -0,0 +1,3 @@ +// Package text provides rudimentary functions for manipulating text in +// paragraphs. +package text diff --git a/vendor/github.com/kr/text/go.mod b/vendor/github.com/kr/text/go.mod new file mode 100644 index 0000000000..fa0528b9a9 --- /dev/null +++ b/vendor/github.com/kr/text/go.mod @@ -0,0 +1,3 @@ +module "github.com/kr/text" + +require "github.com/kr/pty" v1.1.1 diff --git a/vendor/github.com/kr/text/indent.go b/vendor/github.com/kr/text/indent.go new file mode 100644 index 0000000000..4ebac45c09 --- /dev/null +++ b/vendor/github.com/kr/text/indent.go @@ -0,0 +1,74 @@ +package text + +import ( + "io" +) + +// Indent inserts prefix at the beginning of each non-empty line of s. The +// end-of-line marker is NL. +func Indent(s, prefix string) string { + return string(IndentBytes([]byte(s), []byte(prefix))) +} + +// IndentBytes inserts prefix at the beginning of each non-empty line of b. +// The end-of-line marker is NL. +func IndentBytes(b, prefix []byte) []byte { + var res []byte + bol := true + for _, c := range b { + if bol && c != '\n' { + res = append(res, prefix...) + } + res = append(res, c) + bol = c == '\n' + } + return res +} + +// Writer indents each line of its input. +type indentWriter struct { + w io.Writer + bol bool + pre [][]byte + sel int + off int +} + +// NewIndentWriter makes a new write filter that indents the input +// lines. Each line is prefixed in order with the corresponding +// element of pre. If there are more lines than elements, the last +// element of pre is repeated for each subsequent line. +func NewIndentWriter(w io.Writer, pre ...[]byte) io.Writer { + return &indentWriter{ + w: w, + pre: pre, + bol: true, + } +} + +// The only errors returned are from the underlying indentWriter. +func (w *indentWriter) Write(p []byte) (n int, err error) { + for _, c := range p { + if w.bol { + var i int + i, err = w.w.Write(w.pre[w.sel][w.off:]) + w.off += i + if err != nil { + return n, err + } + } + _, err = w.w.Write([]byte{c}) + if err != nil { + return n, err + } + n++ + w.bol = c == '\n' + if w.bol { + w.off = 0 + if w.sel < len(w.pre)-1 { + w.sel++ + } + } + } + return n, nil +} diff --git a/vendor/github.com/kr/text/wrap.go b/vendor/github.com/kr/text/wrap.go new file mode 100644 index 0000000000..b09bb03736 --- /dev/null +++ b/vendor/github.com/kr/text/wrap.go @@ -0,0 +1,86 @@ +package text + +import ( + "bytes" + "math" +) + +var ( + nl = []byte{'\n'} + sp = []byte{' '} +) + +const defaultPenalty = 1e5 + +// Wrap wraps s into a paragraph of lines of length lim, with minimal +// raggedness. +func Wrap(s string, lim int) string { + return string(WrapBytes([]byte(s), lim)) +} + +// WrapBytes wraps b into a paragraph of lines of length lim, with minimal +// raggedness. +func WrapBytes(b []byte, lim int) []byte { + words := bytes.Split(bytes.Replace(bytes.TrimSpace(b), nl, sp, -1), sp) + var lines [][]byte + for _, line := range WrapWords(words, 1, lim, defaultPenalty) { + lines = append(lines, bytes.Join(line, sp)) + } + return bytes.Join(lines, nl) +} + +// WrapWords is the low-level line-breaking algorithm, useful if you need more +// control over the details of the text wrapping process. For most uses, either +// Wrap or WrapBytes will be sufficient and more convenient. +// +// WrapWords splits a list of words into lines with minimal "raggedness", +// treating each byte as one unit, accounting for spc units between adjacent +// words on each line, and attempting to limit lines to lim units. Raggedness +// is the total error over all lines, where error is the square of the +// difference of the length of the line and lim. Too-long lines (which only +// happen when a single word is longer than lim units) have pen penalty units +// added to the error. +func WrapWords(words [][]byte, spc, lim, pen int) [][][]byte { + n := len(words) + + length := make([][]int, n) + for i := 0; i < n; i++ { + length[i] = make([]int, n) + length[i][i] = len(words[i]) + for j := i + 1; j < n; j++ { + length[i][j] = length[i][j-1] + spc + len(words[j]) + } + } + + nbrk := make([]int, n) + cost := make([]int, n) + for i := range cost { + cost[i] = math.MaxInt32 + } + for i := n - 1; i >= 0; i-- { + if length[i][n-1] <= lim || i == n-1 { + cost[i] = 0 + nbrk[i] = n + } else { + for j := i + 1; j < n; j++ { + d := lim - length[i][j-1] + c := d*d + cost[j] + if length[i][j-1] > lim { + c += pen // too-long lines get a worse penalty + } + if c < cost[i] { + cost[i] = c + nbrk[i] = j + } + } + } + } + + var lines [][][]byte + i := 0 + for i < n { + lines = append(lines, words[i:nbrk[i]]) + i = nbrk[i] + } + return lines +} diff --git a/vendor/gopkg.in/check.v1/.travis.yml b/vendor/gopkg.in/check.v1/.travis.yml new file mode 100644 index 0000000000..ead6735fca --- /dev/null +++ b/vendor/gopkg.in/check.v1/.travis.yml @@ -0,0 +1,3 @@ +language: go + +go_import_path: gopkg.in/check.v1 diff --git a/vendor/gopkg.in/check.v1/benchmark.go b/vendor/gopkg.in/check.v1/benchmark.go index 48cb8c8114..46ea9dc6da 100644 --- a/vendor/gopkg.in/check.v1/benchmark.go +++ b/vendor/gopkg.in/check.v1/benchmark.go @@ -1,6 +1,30 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +// Copyright (c) 2012 The Go Authors. 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. +// * Neither the name of Google Inc. nor the names of its +// contributors may 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 +// OWNER 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. package check diff --git a/vendor/gopkg.in/check.v1/check.go b/vendor/gopkg.in/check.v1/check.go index ca8c0f92de..de714c2712 100644 --- a/vendor/gopkg.in/check.v1/check.go +++ b/vendor/gopkg.in/check.v1/check.go @@ -21,6 +21,7 @@ import ( "strconv" "strings" "sync" + "sync/atomic" "time" ) @@ -43,7 +44,7 @@ const ( missedSt ) -type funcStatus int +type funcStatus uint32 // A method value can't reach its own Method structure. type methodType struct { @@ -81,7 +82,7 @@ type C struct { method *methodType kind funcKind testName string - status funcStatus + _status funcStatus logb *logger logw io.Writer done chan *C @@ -93,6 +94,14 @@ type C struct { timer } +func (c *C) status() funcStatus { + return funcStatus(atomic.LoadUint32((*uint32)(&c._status))) +} + +func (c *C) setStatus(s funcStatus) { + atomic.StoreUint32((*uint32)(&c._status), uint32(s)) +} + func (c *C) stopNow() { runtime.Goexit() } @@ -147,7 +156,7 @@ func (td *tempDir) newPath() string { } } result := filepath.Join(td.path, strconv.Itoa(td.counter)) - td.counter += 1 + td.counter++ return result } @@ -230,7 +239,7 @@ func (c *C) logValue(label string, value interface{}) { } } -func (c *C) logMultiLine(s string) { +func formatMultiLine(s string, quote bool) []byte { b := make([]byte, 0, len(s)*2) i := 0 n := len(s) @@ -240,14 +249,23 @@ func (c *C) logMultiLine(s string) { j++ } b = append(b, "... "...) - b = strconv.AppendQuote(b, s[i:j]) - if j < n { + if quote { + b = strconv.AppendQuote(b, s[i:j]) + } else { + b = append(b, s[i:j]...) + b = bytes.TrimSpace(b) + } + if quote && j < n { b = append(b, " +"...) } b = append(b, '\n') i = j } - c.writeLog(b) + return b +} + +func (c *C) logMultiLine(s string) { + c.writeLog(formatMultiLine(s, true)) } func isMultiLine(s string) bool { @@ -265,7 +283,7 @@ func (c *C) logString(issue string) { func (c *C) logCaller(skip int) { // This is a bit heavier than it ought to be. - skip += 1 // Our own frame. + skip++ // Our own frame. pc, callerFile, callerLine, ok := runtime.Caller(skip) if !ok { return @@ -275,7 +293,7 @@ func (c *C) logCaller(skip int) { testFunc := runtime.FuncForPC(c.method.PC()) if runtime.FuncForPC(pc) != testFunc { for { - skip += 1 + skip++ if pc, file, line, ok := runtime.Caller(skip); ok { // Note that the test line may be different on // distinct calls for the same test. Showing @@ -326,7 +344,7 @@ func (c *C) logPanic(skip int, value interface{}) { if name == "Value.call" && strings.HasSuffix(path, valueGo) { continue } - if name == "call16" && strings.Contains(path, asmGo) { + if (name == "call16" || name == "call32") && strings.Contains(path, asmGo) { continue } c.logf("%s:%d\n in %s", nicePath(file), line, name) @@ -451,11 +469,11 @@ func (tracker *resultTracker) _loopRoutine() { // Calls still running. Can't stop. select { // XXX Reindent this (not now to make diff clear) - case c = <-tracker._expectChan: - tracker._waiting += 1 + case <-tracker._expectChan: + tracker._waiting++ case c = <-tracker._doneChan: - tracker._waiting -= 1 - switch c.status { + tracker._waiting-- + switch c.status() { case succeededSt: if c.kind == testKd { if c.mustFail { @@ -489,9 +507,9 @@ func (tracker *resultTracker) _loopRoutine() { select { case tracker._stopChan <- true: return - case c = <-tracker._expectChan: - tracker._waiting += 1 - case c = <-tracker._doneChan: + case <-tracker._expectChan: + tracker._waiting++ + case <-tracker._doneChan: panic("Tracker got an unexpected done call.") } } @@ -559,13 +577,13 @@ func newSuiteRunner(suite interface{}, runConf *RunConf) *suiteRunner { var filterRegexp *regexp.Regexp if conf.Filter != "" { - if regexp, err := regexp.Compile(conf.Filter); err != nil { + regexp, err := regexp.Compile(conf.Filter) + if err != nil { msg := "Bad filter expression: " + err.Error() runner.tracker.result.RunError = errors.New(msg) return runner - } else { - filterRegexp = regexp } + filterRegexp = regexp } for i := 0; i != suiteNumMethods; i++ { @@ -601,15 +619,15 @@ func (runner *suiteRunner) run() *Result { runner.tracker.start() if runner.checkFixtureArgs() { c := runner.runFixture(runner.setUpSuite, "", nil) - if c == nil || c.status == succeededSt { + if c == nil || c.status() == succeededSt { for i := 0; i != len(runner.tests); i++ { c := runner.runTest(runner.tests[i]) - if c.status == fixturePanickedSt { + if c.status() == fixturePanickedSt { runner.skipTests(missedSt, runner.tests[i+1:]) break } } - } else if c != nil && c.status == skippedSt { + } else if c != nil && c.status() == skippedSt { runner.skipTests(skippedSt, runner.tests) } else { runner.skipTests(missedSt, runner.tests) @@ -674,22 +692,22 @@ func (runner *suiteRunner) callDone(c *C) { switch v := value.(type) { case *fixturePanic: if v.status == skippedSt { - c.status = skippedSt + c.setStatus(skippedSt) } else { c.logSoftPanic("Fixture has panicked (see related PANIC)") - c.status = fixturePanickedSt + c.setStatus(fixturePanickedSt) } default: c.logPanic(1, value) - c.status = panickedSt + c.setStatus(panickedSt) } } if c.mustFail { - switch c.status { + switch c.status() { case failedSt: - c.status = succeededSt + c.setStatus(succeededSt) case succeededSt: - c.status = failedSt + c.setStatus(failedSt) c.logString("Error: Test succeeded, but was expected to fail") c.logString("Reason: " + c.reason) } @@ -724,11 +742,11 @@ func (runner *suiteRunner) runFixtureWithPanic(method *methodType, testName stri return nil } c := runner.runFixture(method, testName, logb) - if c != nil && c.status != succeededSt { + if c != nil && c.status() != succeededSt { if skipped != nil { - *skipped = c.status == skippedSt + *skipped = c.status() == skippedSt } - panic(&fixturePanic{c.status, method}) + panic(&fixturePanic{c.status(), method}) } return c } @@ -753,7 +771,7 @@ func (runner *suiteRunner) forkTest(method *methodType) *C { if mt.NumIn() != 1 || mt.In(0) != reflect.TypeOf(c) { // Rather than a plain panic, provide a more helpful message when // the argument type is incorrect. - c.status = panickedSt + c.setStatus(panickedSt) c.logArgPanic(c.method, "*check.C") return } @@ -773,7 +791,7 @@ func (runner *suiteRunner) forkTest(method *methodType) *C { c.StartTimer() c.method.Call([]reflect.Value{reflect.ValueOf(c)}) c.StopTimer() - if c.status != succeededSt || c.duration >= c.benchTime || benchN >= 1e9 { + if c.status() != succeededSt || c.duration >= c.benchTime || benchN >= 1e9 { return } perOpN := int(1e9) @@ -808,7 +826,7 @@ func (runner *suiteRunner) runTest(method *methodType) *C { func (runner *suiteRunner) skipTests(status funcStatus, methods []*methodType) { for _, method := range methods { runner.runFunc(method, testKd, "", nil, func(c *C) { - c.status = status + c.setStatus(status) }) } } @@ -825,7 +843,7 @@ func (runner *suiteRunner) checkFixtureArgs() bool { succeeded = false runner.runFunc(method, fixtureKd, "", nil, func(c *C) { c.logArgPanic(method, "*check.C") - c.status = panickedSt + c.setStatus(panickedSt) }) } } @@ -839,7 +857,7 @@ func (runner *suiteRunner) reportCallStarted(c *C) { func (runner *suiteRunner) reportCallDone(c *C) { runner.tracker.callDone(c) - switch c.status { + switch c.status() { case succeededSt: if c.mustFail { runner.output.WriteCallSuccess("FAIL EXPECTED", c) @@ -862,84 +880,3 @@ func (runner *suiteRunner) reportCallDone(c *C) { runner.output.WriteCallSuccess("MISS", c) } } - -// ----------------------------------------------------------------------- -// Output writer manages atomic output writing according to settings. - -type outputWriter struct { - m sync.Mutex - writer io.Writer - wroteCallProblemLast bool - Stream bool - Verbose bool -} - -func newOutputWriter(writer io.Writer, stream, verbose bool) *outputWriter { - return &outputWriter{writer: writer, Stream: stream, Verbose: verbose} -} - -func (ow *outputWriter) Write(content []byte) (n int, err error) { - ow.m.Lock() - n, err = ow.writer.Write(content) - ow.m.Unlock() - return -} - -func (ow *outputWriter) WriteCallStarted(label string, c *C) { - if ow.Stream { - header := renderCallHeader(label, c, "", "\n") - ow.m.Lock() - ow.writer.Write([]byte(header)) - ow.m.Unlock() - } -} - -func (ow *outputWriter) WriteCallProblem(label string, c *C) { - var prefix string - if !ow.Stream { - prefix = "\n-----------------------------------" + - "-----------------------------------\n" - } - header := renderCallHeader(label, c, prefix, "\n\n") - ow.m.Lock() - ow.wroteCallProblemLast = true - ow.writer.Write([]byte(header)) - if !ow.Stream { - c.logb.WriteTo(ow.writer) - } - ow.m.Unlock() -} - -func (ow *outputWriter) WriteCallSuccess(label string, c *C) { - if ow.Stream || (ow.Verbose && c.kind == testKd) { - // TODO Use a buffer here. - var suffix string - if c.reason != "" { - suffix = " (" + c.reason + ")" - } - if c.status == succeededSt { - suffix += "\t" + c.timerString() - } - suffix += "\n" - if ow.Stream { - suffix += "\n" - } - header := renderCallHeader(label, c, "", suffix) - ow.m.Lock() - // Resist temptation of using line as prefix above due to race. - if !ow.Stream && ow.wroteCallProblemLast { - header = "\n-----------------------------------" + - "-----------------------------------\n" + - header - } - ow.wroteCallProblemLast = false - ow.writer.Write([]byte(header)) - ow.m.Unlock() - } -} - -func renderCallHeader(label string, c *C, prefix, suffix string) string { - pc := c.method.PC() - return fmt.Sprintf("%s%s: %s: %s%s", prefix, label, niceFuncPath(pc), - niceFuncName(pc), suffix) -} diff --git a/vendor/gopkg.in/check.v1/checkers.go b/vendor/gopkg.in/check.v1/checkers.go index bac338729c..cdd7f9aeb2 100644 --- a/vendor/gopkg.in/check.v1/checkers.go +++ b/vendor/gopkg.in/check.v1/checkers.go @@ -4,6 +4,9 @@ import ( "fmt" "reflect" "regexp" + "strings" + + "github.com/kr/pretty" ) // ----------------------------------------------------------------------- @@ -90,6 +93,10 @@ func (checker *notChecker) Info() *CheckerInfo { func (checker *notChecker) Check(params []interface{}, names []string) (result bool, error string) { result, error = checker.sub.Check(params, names) result = !result + if result { + // clear error message if the new result is true + error = "" + } return } @@ -153,6 +160,56 @@ func (checker *notNilChecker) Check(params []interface{}, names []string) (resul // ----------------------------------------------------------------------- // Equals checker. +func diffworthy(a interface{}) bool { + t := reflect.TypeOf(a) + switch t.Kind() { + case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct, reflect.String, reflect.Ptr: + return true + } + return false +} + +// formatUnequal will dump the actual and expected values into a textual +// representation and return an error message containing a diff. +func formatUnequal(obtained interface{}, expected interface{}) string { + // We do not do diffs for basic types because go-check already + // shows them very cleanly. + if !diffworthy(obtained) || !diffworthy(expected) { + return "" + } + + // Handle strings, short strings are ignored (go-check formats + // them very nicely already). We do multi-line strings by + // generating two string slices and using kr.Diff to compare + // those (kr.Diff does not do string diffs by itself). + aStr, aOK := obtained.(string) + bStr, bOK := expected.(string) + if aOK && bOK { + l1 := strings.Split(aStr, "\n") + l2 := strings.Split(bStr, "\n") + // the "2" here is a bit arbitrary + if len(l1) > 2 && len(l2) > 2 { + diff := pretty.Diff(l1, l2) + return fmt.Sprintf(`String difference: +%s`, formatMultiLine(strings.Join(diff, "\n"), false)) + } + // string too short + return "" + } + + // generic diff + diff := pretty.Diff(obtained, expected) + if len(diff) == 0 { + // No diff, this happens when e.g. just struct + // pointers are different but the structs have + // identical values. + return "" + } + + return fmt.Sprintf(`Difference: +%s`, formatMultiLine(strings.Join(diff, "\n"), false)) +} + type equalsChecker struct { *CheckerInfo } @@ -175,7 +232,12 @@ func (checker *equalsChecker) Check(params []interface{}, names []string) (resul error = fmt.Sprint(v) } }() - return params[0] == params[1], "" + + result = params[0] == params[1] + if !result { + error = formatUnequal(params[0], params[1]) + } + return } // ----------------------------------------------------------------------- @@ -200,7 +262,11 @@ var DeepEquals Checker = &deepEqualsChecker{ } func (checker *deepEqualsChecker) Check(params []interface{}, names []string) (result bool, error string) { - return reflect.DeepEqual(params[0], params[1]), "" + result = reflect.DeepEqual(params[0], params[1]) + if !result { + error = formatUnequal(params[0], params[1]) + } + return } // ----------------------------------------------------------------------- @@ -212,7 +278,7 @@ type hasLenChecker struct { // The HasLen checker verifies that the obtained value has the // provided length. In many cases this is superior to using Equals -// in conjuction with the len function because in case the check +// in conjunction with the len function because in case the check // fails the value itself will be printed, instead of its length, // providing more details for figuring the problem. // diff --git a/vendor/gopkg.in/check.v1/helpers.go b/vendor/gopkg.in/check.v1/helpers.go index 4b6c26da45..58a733b50f 100644 --- a/vendor/gopkg.in/check.v1/helpers.go +++ b/vendor/gopkg.in/check.v1/helpers.go @@ -16,7 +16,7 @@ func (c *C) TestName() string { // Failed returns whether the currently running test has already failed. func (c *C) Failed() bool { - return c.status == failedSt + return c.status() == failedSt } // Fail marks the currently running test as failed. @@ -25,7 +25,7 @@ func (c *C) Failed() bool { // what went wrong. The higher level helper functions will fail the test // and do the logging properly. func (c *C) Fail() { - c.status = failedSt + c.setStatus(failedSt) } // FailNow marks the currently running test as failed and stops running it. @@ -40,7 +40,7 @@ func (c *C) FailNow() { // Succeed marks the currently running test as succeeded, undoing any // previous failures. func (c *C) Succeed() { - c.status = succeededSt + c.setStatus(succeededSt) } // SucceedNow marks the currently running test as succeeded, undoing any @@ -72,7 +72,7 @@ func (c *C) Skip(reason string) { panic("Missing reason why the test is being skipped") } c.reason = reason - c.status = skippedSt + c.setStatus(skippedSt) c.stopNow() } diff --git a/vendor/gopkg.in/check.v1/reporter.go b/vendor/gopkg.in/check.v1/reporter.go new file mode 100644 index 0000000000..fb04f76f64 --- /dev/null +++ b/vendor/gopkg.in/check.v1/reporter.go @@ -0,0 +1,88 @@ +package check + +import ( + "fmt" + "io" + "sync" +) + +// ----------------------------------------------------------------------- +// Output writer manages atomic output writing according to settings. + +type outputWriter struct { + m sync.Mutex + writer io.Writer + wroteCallProblemLast bool + Stream bool + Verbose bool +} + +func newOutputWriter(writer io.Writer, stream, verbose bool) *outputWriter { + return &outputWriter{writer: writer, Stream: stream, Verbose: verbose} +} + +func (ow *outputWriter) Write(content []byte) (n int, err error) { + ow.m.Lock() + n, err = ow.writer.Write(content) + ow.m.Unlock() + return +} + +func (ow *outputWriter) WriteCallStarted(label string, c *C) { + if ow.Stream { + header := renderCallHeader(label, c, "", "\n") + ow.m.Lock() + ow.writer.Write([]byte(header)) + ow.m.Unlock() + } +} + +func (ow *outputWriter) WriteCallProblem(label string, c *C) { + var prefix string + if !ow.Stream { + prefix = "\n-----------------------------------" + + "-----------------------------------\n" + } + header := renderCallHeader(label, c, prefix, "\n\n") + ow.m.Lock() + ow.wroteCallProblemLast = true + ow.writer.Write([]byte(header)) + if !ow.Stream { + c.logb.WriteTo(ow.writer) + } + ow.m.Unlock() +} + +func (ow *outputWriter) WriteCallSuccess(label string, c *C) { + if ow.Stream || (ow.Verbose && c.kind == testKd) { + // TODO Use a buffer here. + var suffix string + if c.reason != "" { + suffix = " (" + c.reason + ")" + } + if c.status() == succeededSt { + suffix += "\t" + c.timerString() + } + suffix += "\n" + if ow.Stream { + suffix += "\n" + } + header := renderCallHeader(label, c, "", suffix) + ow.m.Lock() + // Resist temptation of using line as prefix above due to race. + if !ow.Stream && ow.wroteCallProblemLast { + header = "\n-----------------------------------" + + "-----------------------------------\n" + + header + } + ow.wroteCallProblemLast = false + ow.writer.Write([]byte(header)) + ow.m.Unlock() + } +} + +func renderCallHeader(label string, c *C, prefix, suffix string) string { + pc := c.method.PC() + return fmt.Sprintf("%s%s: %s: %s%s", prefix, label, niceFuncPath(pc), + niceFuncName(pc), suffix) +}