From 9685b4767fc49c4a43ba762a5afbcd175f3d9245 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Sat, 17 Oct 2015 13:41:44 +0200 Subject: [PATCH] Vendoring shakers library and update go-check The shakers library defines a bunch of go-check checkers to ease writing tests. Signed-off-by: Vincent Demeester --- hack/vendor.sh | 3 +- pkg/integration/checker/checker.go | 61 ++-- pkg/integration/checker/checker_test.go | 57 ---- .../github.com/go-check/check/benchmark.go | 30 +- vendor/src/github.com/go-check/check/check.go | 53 +-- .../src/github.com/go-check/check/helpers.go | 8 +- .../github.com/vdemeester/shakers/.gitignore | 4 + .../github.com/vdemeester/shakers/Dockerfile | 12 + .../github.com/vdemeester/shakers/Makefile | 40 +++ .../github.com/vdemeester/shakers/README.md | 24 ++ .../src/github.com/vdemeester/shakers/bool.go | 46 +++ .../github.com/vdemeester/shakers/circle.yml | 11 + .../github.com/vdemeester/shakers/common.go | 310 ++++++++++++++++++ .../github.com/vdemeester/shakers/glide.yaml | 4 + .../github.com/vdemeester/shakers/string.go | 168 ++++++++++ .../src/github.com/vdemeester/shakers/time.go | 234 +++++++++++++ 16 files changed, 941 insertions(+), 124 deletions(-) delete mode 100644 pkg/integration/checker/checker_test.go create mode 100644 vendor/src/github.com/vdemeester/shakers/.gitignore create mode 100644 vendor/src/github.com/vdemeester/shakers/Dockerfile create mode 100644 vendor/src/github.com/vdemeester/shakers/Makefile create mode 100644 vendor/src/github.com/vdemeester/shakers/README.md create mode 100644 vendor/src/github.com/vdemeester/shakers/bool.go create mode 100644 vendor/src/github.com/vdemeester/shakers/circle.yml create mode 100644 vendor/src/github.com/vdemeester/shakers/common.go create mode 100644 vendor/src/github.com/vdemeester/shakers/glide.yaml create mode 100644 vendor/src/github.com/vdemeester/shakers/string.go create mode 100644 vendor/src/github.com/vdemeester/shakers/time.go diff --git a/hack/vendor.sh b/hack/vendor.sh index f78e444976..73b3740c88 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -9,7 +9,7 @@ source 'hack/.vendor-helpers.sh' clone git github.com/Azure/go-ansiterm 70b2c90b260171e829f1ebd7c17f600c11858dbe clone git github.com/Sirupsen/logrus v0.8.2 # logrus is a common dependency among multiple deps clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a -clone git github.com/go-check/check 64131543e7896d5bcc6bd5a76287eb75ea96c673 +clone git github.com/go-check/check 11d3bc7aa68e238947792f30573146a3231fc0f1 clone git github.com/gorilla/context 14f550f51a clone git github.com/gorilla/mux e444e69cbd clone git github.com/kr/pty 5cf931ef8f @@ -17,6 +17,7 @@ clone git github.com/mattn/go-sqlite3 v1.1.0 clone git github.com/microsoft/hcsshim 7f646aa6b26bcf90caee91e93cde4a80d0d8a83e clone git github.com/mistifyio/go-zfs v2.1.1 clone git github.com/tchap/go-patricia v2.1.0 +clone git github.com/vdemeester/shakers 3c10293ce22b900c27acad7b28656196fcc2f73b clone git golang.org/x/net 3cffabab72adf04f8e3b01c5baf775361837b5fe https://github.com/golang/net.git #get libnetwork packages diff --git a/pkg/integration/checker/checker.go b/pkg/integration/checker/checker.go index 45915c80f8..a5314994cd 100644 --- a/pkg/integration/checker/checker.go +++ b/pkg/integration/checker/checker.go @@ -2,17 +2,14 @@ package checker import ( - "fmt" - "strings" - "github.com/go-check/check" + "github.com/vdemeester/shakers" ) // As a commodity, we bring all check.Checker variables into the current namespace to avoid having // to think about check.X versus checker.X. var ( DeepEquals = check.DeepEquals - Equals = check.Equals ErrorMatches = check.ErrorMatches FitsTypeOf = check.FitsTypeOf HasLen = check.HasLen @@ -23,37 +20,27 @@ var ( NotNil = check.NotNil PanicMatches = check.PanicMatches Panics = check.Panics + + Contains = shakers.Contains + ContainsAny = shakers.ContainsAny + Count = shakers.Count + Equals = shakers.Equals + EqualFold = shakers.EqualFold + False = shakers.False + GreaterOrEqualThan = shakers.GreaterOrEqualThan + GreaterThan = shakers.GreaterThan + HasPrefix = shakers.HasPrefix + HasSuffix = shakers.HasSuffix + Index = shakers.Index + IndexAny = shakers.IndexAny + IsAfter = shakers.IsAfter + IsBefore = shakers.IsBefore + IsBetween = shakers.IsBetween + IsLower = shakers.IsLower + IsUpper = shakers.IsUpper + LessOrEqualThan = shakers.LessOrEqualThan + LessThan = shakers.LessThan + TimeEquals = shakers.TimeEquals + True = shakers.True + TimeIgnore = shakers.TimeIgnore ) - -// Contains checker verifies that string value contains a substring. -var Contains check.Checker = &containsChecker{ - &check.CheckerInfo{ - Name: "Contains", - Params: []string{"value", "substring"}, - }, -} - -type containsChecker struct { - *check.CheckerInfo -} - -func (checker *containsChecker) Check(params []interface{}, names []string) (bool, string) { - return contains(params[0], params[1]) -} - -func contains(value, substring interface{}) (bool, string) { - substringStr, ok := substring.(string) - if !ok { - return false, "Substring must be a string" - } - valueStr, valueIsStr := value.(string) - if !valueIsStr { - if valueWithStr, valueHasStr := value.(fmt.Stringer); valueHasStr { - valueStr, valueIsStr = valueWithStr.String(), true - } - } - if valueIsStr { - return strings.Contains(valueStr, substringStr), "" - } - return false, "Obtained value is not a string and has no .String()" -} diff --git a/pkg/integration/checker/checker_test.go b/pkg/integration/checker/checker_test.go deleted file mode 100644 index b8145faf9a..0000000000 --- a/pkg/integration/checker/checker_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package checker - -import ( - "reflect" - "testing" - - "github.com/go-check/check" -) - -func Test(t *testing.T) { - check.TestingT(t) -} - -func init() { - check.Suite(&CheckersS{}) -} - -type CheckersS struct{} - -var _ = check.Suite(&CheckersS{}) - -func testInfo(c *check.C, checker check.Checker, name string, paramNames []string) { - info := checker.Info() - if info.Name != name { - c.Fatalf("Got name %s, expected %s", info.Name, name) - } - if !reflect.DeepEqual(info.Params, paramNames) { - c.Fatalf("Got param names %#v, expected %#v", info.Params, paramNames) - } -} - -func testCheck(c *check.C, checker check.Checker, expectedResult bool, expectedError string, params ...interface{}) ([]interface{}, []string) { - info := checker.Info() - if len(params) != len(info.Params) { - c.Fatalf("unexpected param count in test; expected %d got %d", len(info.Params), len(params)) - } - names := append([]string{}, info.Params...) - result, error := checker.Check(params, names) - if result != expectedResult || error != expectedError { - c.Fatalf("%s.Check(%#v) returned (%#v, %#v) rather than (%#v, %#v)", - info.Name, params, result, error, expectedResult, expectedError) - } - return params, names -} - -func (s *CheckersS) TestContains(c *check.C) { - testInfo(c, Contains, "Contains", []string{"value", "substring"}) - - testCheck(c, Contains, true, "", "abcd", "bc") - testCheck(c, Contains, false, "", "abcd", "efg") - testCheck(c, Contains, false, "", "", "bc") - testCheck(c, Contains, true, "", "abcd", "") - testCheck(c, Contains, true, "", "", "") - - testCheck(c, Contains, false, "Obtained value is not a string and has no .String()", 12, "1") - testCheck(c, Contains, false, "Substring must be a string", "", 1) -} diff --git a/vendor/src/github.com/go-check/check/benchmark.go b/vendor/src/github.com/go-check/check/benchmark.go index 48cb8c8114..46ea9dc6da 100644 --- a/vendor/src/github.com/go-check/check/benchmark.go +++ b/vendor/src/github.com/go-check/check/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/src/github.com/go-check/check/check.go b/vendor/src/github.com/go-check/check/check.go index ca8c0f92de..c99392a25b 100644 --- a/vendor/src/github.com/go-check/check/check.go +++ b/vendor/src/github.com/go-check/check/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() } @@ -326,7 +335,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) @@ -455,7 +464,7 @@ func (tracker *resultTracker) _loopRoutine() { tracker._waiting += 1 case c = <-tracker._doneChan: tracker._waiting -= 1 - switch c.status { + switch c.status() { case succeededSt: if c.kind == testKd { if c.mustFail { @@ -601,15 +610,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 +683,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 +733,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 +762,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 +782,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 +817,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 +834,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 +848,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) @@ -917,7 +926,7 @@ func (ow *outputWriter) WriteCallSuccess(label string, c *C) { if c.reason != "" { suffix = " (" + c.reason + ")" } - if c.status == succeededSt { + if c.status() == succeededSt { suffix += "\t" + c.timerString() } suffix += "\n" diff --git a/vendor/src/github.com/go-check/check/helpers.go b/vendor/src/github.com/go-check/check/helpers.go index 4b6c26da45..58a733b50f 100644 --- a/vendor/src/github.com/go-check/check/helpers.go +++ b/vendor/src/github.com/go-check/check/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/src/github.com/vdemeester/shakers/.gitignore b/vendor/src/github.com/vdemeester/shakers/.gitignore new file mode 100644 index 0000000000..a9243971be --- /dev/null +++ b/vendor/src/github.com/vdemeester/shakers/.gitignore @@ -0,0 +1,4 @@ +Godeps/_workspace/bin +Godeps/_workspace/pkg + +*.test diff --git a/vendor/src/github.com/vdemeester/shakers/Dockerfile b/vendor/src/github.com/vdemeester/shakers/Dockerfile new file mode 100644 index 0000000000..12c09a0d2b --- /dev/null +++ b/vendor/src/github.com/vdemeester/shakers/Dockerfile @@ -0,0 +1,12 @@ +FROM golang:1.5 + +RUN go get golang.org/x/tools/cmd/cover +RUN go get github.com/golang/lint/golint +RUN go get golang.org/x/tools/cmd/vet + +WORKDIR /go/src/github.com/vdemeester/shakers + +# enable GO15VENDOREXPERIMENT +ENV GO15VENDOREXPERIMENT 1 + +COPY . /go/src/github.com/vdemeester/shakers diff --git a/vendor/src/github.com/vdemeester/shakers/Makefile b/vendor/src/github.com/vdemeester/shakers/Makefile new file mode 100644 index 0000000000..10b3be708e --- /dev/null +++ b/vendor/src/github.com/vdemeester/shakers/Makefile @@ -0,0 +1,40 @@ +.PHONY: all + +SHAKERS_MOUNT := $(if $(BIND_DIR),-v "$(CURDIR)/$(BIND_DIR):/go/src/github.com/vdemeester/shakers/$(BIND_DIR)") + +GIT_BRANCH := $(shell git rev-parse --abbrev-ref HEAD 2>/dev/null) +SHAKERS_DEV_IMAGE := shakers-dev$(if $(GIT_BRANCH),:$(GIT_BRANCH)) + +DOCKER_RUN_SHAKERS := docker run $(if $(CIRCLECI),,--rm) -it $(SHAKERS_ENVS) $(SHAKERS_MOUNT) "$(SHAKERS_DEV_IMAGE)" + +print-%: ; @echo $*=$($*) + +default: binary + +binary: build + $(DOCKER_RUN_SHAKERS) ./script/make.sh binary + +test-unit: build + $(DOCKER_RUN_SHAKERS) ./script/make.sh test-unit + +validate: build + $(DOCKER_RUN_SHAKERS) ./script/make.sh validate-gofmt validate-golint validate-govet + +validate-govet: build + $(DOCKER_RUN_SHAKERS) ./script/make.sh validate-govet + +validate-golint: build + $(DOCKER_RUN_SHAKERS) ./script/make.sh validate-golint + +validate-gofmt: build + $(DOCKER_RUN_SHAKERS) ./script/make.sh validate-gofmt + +build: + docker build -t "$(SHAKERS_DEV_IMAGE)" . + +shell: build + $(DOCKER_RUN_SHAKERS) /bin/bash + +run-dev: + go build + ./traefik diff --git a/vendor/src/github.com/vdemeester/shakers/README.md b/vendor/src/github.com/vdemeester/shakers/README.md new file mode 100644 index 0000000000..05417f9e1c --- /dev/null +++ b/vendor/src/github.com/vdemeester/shakers/README.md @@ -0,0 +1,24 @@ +# Shakers +🐹 + 🐙 = 😽 [![Circle CI](https://circleci.com/gh/vdemeester/shakers.svg?style=svg)](https://circleci.com/gh/vdemeester/shakers) + +A collection of `go-check` Checkers to ease the use of it. + +## Building and testing it + +You need either [docker](https://github.com/docker/docker), or `go` +and `godep` in order to build and test shakers. + +### Using Docker and Makefile + +You need to run the ``test-unit`` target. +```bash +$ make test-unit +docker build -t "shakers-dev:master" . +# […] +docker run --rm -it "shakers-dev:master" ./script/make.sh test-unit +---> Making bundle: test-unit (in .) ++ go test -cover -coverprofile=cover.out . +ok github.com/vdemeester/shakers 0.015s coverage: 96.0% of statements + +Test success +``` diff --git a/vendor/src/github.com/vdemeester/shakers/bool.go b/vendor/src/github.com/vdemeester/shakers/bool.go new file mode 100644 index 0000000000..ab2a993c3d --- /dev/null +++ b/vendor/src/github.com/vdemeester/shakers/bool.go @@ -0,0 +1,46 @@ +package shakers + +import ( + "github.com/go-check/check" +) + +// True checker verifies the obtained value is true +// +// c.Assert(myBool, True) +// +var True check.Checker = &boolChecker{ + &check.CheckerInfo{ + Name: "True", + Params: []string{"obtained"}, + }, + true, +} + +// False checker verifies the obtained value is false +// +// c.Assert(myBool, False) +// +var False check.Checker = &boolChecker{ + &check.CheckerInfo{ + Name: "False", + Params: []string{"obtained"}, + }, + false, +} + +type boolChecker struct { + *check.CheckerInfo + expected bool +} + +func (checker *boolChecker) Check(params []interface{}, names []string) (bool, string) { + return is(checker.expected, params[0]) +} + +func is(expected bool, obtained interface{}) (bool, string) { + obtainedBool, ok := obtained.(bool) + if !ok { + return false, "obtained value must be a bool." + } + return obtainedBool == expected, "" +} diff --git a/vendor/src/github.com/vdemeester/shakers/circle.yml b/vendor/src/github.com/vdemeester/shakers/circle.yml new file mode 100644 index 0000000000..0298aad0c8 --- /dev/null +++ b/vendor/src/github.com/vdemeester/shakers/circle.yml @@ -0,0 +1,11 @@ +machine: + services: + - docker + +dependencies: + override: + - make validate + +test: + override: + - make test-unit diff --git a/vendor/src/github.com/vdemeester/shakers/common.go b/vendor/src/github.com/vdemeester/shakers/common.go new file mode 100644 index 0000000000..a2245c682a --- /dev/null +++ b/vendor/src/github.com/vdemeester/shakers/common.go @@ -0,0 +1,310 @@ +package shakers + +import ( + "reflect" + "time" + + "github.com/go-check/check" +) + +// As a commodity, we bring all check.Checker variables into the current namespace to avoid having +// to think about check.X versus checker.X. +var ( + DeepEquals = check.DeepEquals + ErrorMatches = check.ErrorMatches + FitsTypeOf = check.FitsTypeOf + HasLen = check.HasLen + Implements = check.Implements + IsNil = check.IsNil + Matches = check.Matches + Not = check.Not + NotNil = check.NotNil + PanicMatches = check.PanicMatches + Panics = check.Panics +) + +// Equaler is an interface implemented if the type has a Equal method. +// This is used to compare struct using shakers.Equals. +type Equaler interface { + Equal(Equaler) bool +} + +// Equals checker verifies the obtained value is equal to the specified one. +// It's is smart in a wait that it supports several *types* (built-in, Equaler, +// time.Time) +// +// c.Assert(myStruct, Equals, aStruct, check.Commentf("bouuuhh")) +// c.Assert(myTime, Equals, aTime, check.Commentf("bouuuhh")) +// +var Equals check.Checker = &equalChecker{ + &check.CheckerInfo{ + Name: "Equals", + Params: []string{"obtained", "expected"}, + }, +} + +type equalChecker struct { + *check.CheckerInfo +} + +func (checker *equalChecker) Check(params []interface{}, names []string) (bool, string) { + return isEqual(params[0], params[1]) +} + +func isEqual(obtained, expected interface{}) (bool, string) { + switch obtained.(type) { + case time.Time: + return timeEquals(obtained, expected) + case Equaler: + return equalerEquals(obtained, expected) + default: + if reflect.TypeOf(obtained) != reflect.TypeOf(expected) { + return false, "obtained value and expected value have not the same type." + } + return obtained == expected, "" + } +} + +func equalerEquals(obtained, expected interface{}) (bool, string) { + expectedEqualer, ok := expected.(Equaler) + if !ok { + return false, "expected value must be an Equaler - implementing Equal(Equaler)." + } + obtainedEqualer, ok := obtained.(Equaler) + if !ok { + return false, "obtained value must be an Equaler - implementing Equal(Equaler)." + } + return obtainedEqualer.Equal(expectedEqualer), "" +} + +// GreaterThan checker verifies the obtained value is greater than the specified one. +// It's is smart in a wait that it supports several *types* (built-in, time.Time) +// +// c.Assert(myTime, GreaterThan, aTime, check.Commentf("bouuuhh")) +// c.Assert(myInt, GreaterThan, 2, check.Commentf("bouuuhh")) +// +var GreaterThan check.Checker = &greaterThanChecker{ + &check.CheckerInfo{ + Name: "GreaterThan", + Params: []string{"obtained", "expected"}, + }, +} + +type greaterThanChecker struct { + *check.CheckerInfo +} + +func (checker *greaterThanChecker) Check(params []interface{}, names []string) (bool, string) { + return greaterThan(params[0], params[1]) +} + +func greaterThan(obtained, expected interface{}) (bool, string) { + if _, ok := obtained.(time.Time); ok { + return isAfter(obtained, expected) + } + if reflect.TypeOf(obtained) != reflect.TypeOf(expected) { + return false, "obtained value and expected value have not the same type." + } + switch v := obtained.(type) { + case float32: + return v > expected.(float32), "" + case float64: + return v > expected.(float64), "" + case int: + return v > expected.(int), "" + case int8: + return v > expected.(int8), "" + case int16: + return v > expected.(int16), "" + case int32: + return v > expected.(int32), "" + case int64: + return v > expected.(int64), "" + case uint: + return v > expected.(uint), "" + case uint8: + return v > expected.(uint8), "" + case uint16: + return v > expected.(uint16), "" + case uint32: + return v > expected.(uint32), "" + case uint64: + return v > expected.(uint64), "" + default: + return false, "obtained value type not supported." + } +} + +// GreaterOrEqualThan checker verifies the obtained value is greater or equal than the specified one. +// It's is smart in a wait that it supports several *types* (built-in, time.Time) +// +// c.Assert(myTime, GreaterOrEqualThan, aTime, check.Commentf("bouuuhh")) +// c.Assert(myInt, GreaterOrEqualThan, 2, check.Commentf("bouuuhh")) +// +var GreaterOrEqualThan check.Checker = &greaterOrEqualThanChecker{ + &check.CheckerInfo{ + Name: "GreaterOrEqualThan", + Params: []string{"obtained", "expected"}, + }, +} + +type greaterOrEqualThanChecker struct { + *check.CheckerInfo +} + +func (checker *greaterOrEqualThanChecker) Check(params []interface{}, names []string) (bool, string) { + return greaterOrEqualThan(params[0], params[1]) +} + +func greaterOrEqualThan(obtained, expected interface{}) (bool, string) { + if _, ok := obtained.(time.Time); ok { + return isAfter(obtained, expected) + } + if reflect.TypeOf(obtained) != reflect.TypeOf(expected) { + return false, "obtained value and expected value have not the same type." + } + switch v := obtained.(type) { + case float32: + return v >= expected.(float32), "" + case float64: + return v >= expected.(float64), "" + case int: + return v >= expected.(int), "" + case int8: + return v >= expected.(int8), "" + case int16: + return v >= expected.(int16), "" + case int32: + return v >= expected.(int32), "" + case int64: + return v >= expected.(int64), "" + case uint: + return v >= expected.(uint), "" + case uint8: + return v >= expected.(uint8), "" + case uint16: + return v >= expected.(uint16), "" + case uint32: + return v >= expected.(uint32), "" + case uint64: + return v >= expected.(uint64), "" + default: + return false, "obtained value type not supported." + } +} + +// LessThan checker verifies the obtained value is less than the specified one. +// It's is smart in a wait that it supports several *types* (built-in, time.Time) +// +// c.Assert(myTime, LessThan, aTime, check.Commentf("bouuuhh")) +// c.Assert(myInt, LessThan, 2, check.Commentf("bouuuhh")) +// +var LessThan check.Checker = &lessThanChecker{ + &check.CheckerInfo{ + Name: "LessThan", + Params: []string{"obtained", "expected"}, + }, +} + +type lessThanChecker struct { + *check.CheckerInfo +} + +func (checker *lessThanChecker) Check(params []interface{}, names []string) (bool, string) { + return lessThan(params[0], params[1]) +} + +func lessThan(obtained, expected interface{}) (bool, string) { + if _, ok := obtained.(time.Time); ok { + return isBefore(obtained, expected) + } + if reflect.TypeOf(obtained) != reflect.TypeOf(expected) { + return false, "obtained value and expected value have not the same type." + } + switch v := obtained.(type) { + case float32: + return v < expected.(float32), "" + case float64: + return v < expected.(float64), "" + case int: + return v < expected.(int), "" + case int8: + return v < expected.(int8), "" + case int16: + return v < expected.(int16), "" + case int32: + return v < expected.(int32), "" + case int64: + return v < expected.(int64), "" + case uint: + return v < expected.(uint), "" + case uint8: + return v < expected.(uint8), "" + case uint16: + return v < expected.(uint16), "" + case uint32: + return v < expected.(uint32), "" + case uint64: + return v < expected.(uint64), "" + default: + return false, "obtained value type not supported." + } +} + +// LessOrEqualThan checker verifies the obtained value is less or equal than the specified one. +// It's is smart in a wait that it supports several *types* (built-in, time.Time) +// +// c.Assert(myTime, LessThan, aTime, check.Commentf("bouuuhh")) +// c.Assert(myInt, LessThan, 2, check.Commentf("bouuuhh")) +// +var LessOrEqualThan check.Checker = &lessOrEqualThanChecker{ + &check.CheckerInfo{ + Name: "LessOrEqualThan", + Params: []string{"obtained", "expected"}, + }, +} + +type lessOrEqualThanChecker struct { + *check.CheckerInfo +} + +func (checker *lessOrEqualThanChecker) Check(params []interface{}, names []string) (bool, string) { + return lessOrEqualThan(params[0], params[1]) +} + +func lessOrEqualThan(obtained, expected interface{}) (bool, string) { + if _, ok := obtained.(time.Time); ok { + return isBefore(obtained, expected) + } + if reflect.TypeOf(obtained) != reflect.TypeOf(expected) { + return false, "obtained value and expected value have not the same type." + } + switch v := obtained.(type) { + case float32: + return v <= expected.(float32), "" + case float64: + return v <= expected.(float64), "" + case int: + return v <= expected.(int), "" + case int8: + return v <= expected.(int8), "" + case int16: + return v <= expected.(int16), "" + case int32: + return v <= expected.(int32), "" + case int64: + return v <= expected.(int64), "" + case uint: + return v <= expected.(uint), "" + case uint8: + return v <= expected.(uint8), "" + case uint16: + return v <= expected.(uint16), "" + case uint32: + return v <= expected.(uint32), "" + case uint64: + return v <= expected.(uint64), "" + default: + return false, "obtained value type not supported." + } +} diff --git a/vendor/src/github.com/vdemeester/shakers/glide.yaml b/vendor/src/github.com/vdemeester/shakers/glide.yaml new file mode 100644 index 0000000000..3d9c7f45e6 --- /dev/null +++ b/vendor/src/github.com/vdemeester/shakers/glide.yaml @@ -0,0 +1,4 @@ +package: main +import: + - package: github.com/go-check/check + ref: 11d3bc7aa68e238947792f30573146a3231fc0f1 diff --git a/vendor/src/github.com/vdemeester/shakers/string.go b/vendor/src/github.com/vdemeester/shakers/string.go new file mode 100644 index 0000000000..75ecb10d50 --- /dev/null +++ b/vendor/src/github.com/vdemeester/shakers/string.go @@ -0,0 +1,168 @@ +// Package shakers provide some checker implementation the go-check.Checker interface. +package shakers + +import ( + "fmt" + "strings" + + "github.com/go-check/check" +) + +// Contains checker verifies that obtained value contains a substring. +var Contains check.Checker = &substringChecker{ + &check.CheckerInfo{ + Name: "Contains", + Params: []string{"obtained", "substring"}, + }, + strings.Contains, +} + +// ContainsAny checker verifies that any Unicode code points in chars +// are in the obtained string. +var ContainsAny check.Checker = &substringChecker{ + &check.CheckerInfo{ + Name: "ContainsAny", + Params: []string{"obtained", "chars"}, + }, + strings.ContainsAny, +} + +// HasPrefix checker verifies that obtained value has the specified substring as prefix +var HasPrefix check.Checker = &substringChecker{ + &check.CheckerInfo{ + Name: "HasPrefix", + Params: []string{"obtained", "prefix"}, + }, + strings.HasPrefix, +} + +// HasSuffix checker verifies that obtained value has the specified substring as prefix +var HasSuffix check.Checker = &substringChecker{ + &check.CheckerInfo{ + Name: "HasSuffix", + Params: []string{"obtained", "suffix"}, + }, + strings.HasSuffix, +} + +// EqualFold checker verifies that obtained value is, interpreted as UTF-8 strings, are equal under Unicode case-folding. +var EqualFold check.Checker = &substringChecker{ + &check.CheckerInfo{ + Name: "EqualFold", + Params: []string{"obtained", "expected"}, + }, + strings.EqualFold, +} + +type substringChecker struct { + *check.CheckerInfo + substringFunction func(string, string) bool +} + +func (checker *substringChecker) Check(params []interface{}, names []string) (bool, string) { + obtained := params[0] + substring := params[1] + substringStr, ok := substring.(string) + if !ok { + return false, fmt.Sprintf("%s value must be a string.", names[1]) + } + obtainedString, obtainedIsStr := obtained.(string) + if !obtainedIsStr { + if obtainedWithStringer, obtainedHasStringer := obtained.(fmt.Stringer); obtainedHasStringer { + obtainedString, obtainedIsStr = obtainedWithStringer.String(), true + } + } + if obtainedIsStr { + return checker.substringFunction(obtainedString, substringStr), "" + } + return false, "obtained value is not a string and has no .String()." +} + +// IndexAny checker verifies that the index of the first instance of any Unicode code point from chars in the obtained value is equal to expected +var IndexAny check.Checker = &substringCountChecker{ + &check.CheckerInfo{ + Name: "IndexAny", + Params: []string{"obtained", "chars", "expected"}, + }, + strings.IndexAny, +} + +// Index checker verifies that the index of the first instance of sep in the obtained value is equal to expected +var Index check.Checker = &substringCountChecker{ + &check.CheckerInfo{ + Name: "Index", + Params: []string{"obtained", "sep", "expected"}, + }, + strings.Index, +} + +// Count checker verifies that obtained value has the specified number of non-overlapping instances of sep +var Count check.Checker = &substringCountChecker{ + &check.CheckerInfo{ + Name: "Count", + Params: []string{"obtained", "sep", "expected"}, + }, + strings.Count, +} + +type substringCountChecker struct { + *check.CheckerInfo + substringFunction func(string, string) int +} + +func (checker *substringCountChecker) Check(params []interface{}, names []string) (bool, string) { + obtained := params[0] + substring := params[1] + expected := params[2] + substringStr, ok := substring.(string) + if !ok { + return false, fmt.Sprintf("%s value must be a string.", names[1]) + } + obtainedString, obtainedIsStr := obtained.(string) + if !obtainedIsStr { + if obtainedWithStringer, obtainedHasStringer := obtained.(fmt.Stringer); obtainedHasStringer { + obtainedString, obtainedIsStr = obtainedWithStringer.String(), true + } + } + if obtainedIsStr { + return checker.substringFunction(obtainedString, substringStr) == expected, "" + } + return false, "obtained value is not a string and has no .String()." +} + +// IsLower checker verifies that the obtained value is in lower case +var IsLower check.Checker = &stringTransformChecker{ + &check.CheckerInfo{ + Name: "IsLower", + Params: []string{"obtained"}, + }, + strings.ToLower, +} + +// IsUpper checker verifies that the obtained value is in lower case +var IsUpper check.Checker = &stringTransformChecker{ + &check.CheckerInfo{ + Name: "IsUpper", + Params: []string{"obtained"}, + }, + strings.ToUpper, +} + +type stringTransformChecker struct { + *check.CheckerInfo + stringFunction func(string) string +} + +func (checker *stringTransformChecker) Check(params []interface{}, names []string) (bool, string) { + obtained := params[0] + obtainedString, obtainedIsStr := obtained.(string) + if !obtainedIsStr { + if obtainedWithStringer, obtainedHasStringer := obtained.(fmt.Stringer); obtainedHasStringer { + obtainedString, obtainedIsStr = obtainedWithStringer.String(), true + } + } + if obtainedIsStr { + return checker.stringFunction(obtainedString) == obtainedString, "" + } + return false, "obtained value is not a string and has no .String()." +} diff --git a/vendor/src/github.com/vdemeester/shakers/time.go b/vendor/src/github.com/vdemeester/shakers/time.go new file mode 100644 index 0000000000..0da8d00598 --- /dev/null +++ b/vendor/src/github.com/vdemeester/shakers/time.go @@ -0,0 +1,234 @@ +package shakers + +import ( + "fmt" + "time" + + "github.com/go-check/check" +) + +// Default format when parsing (in addition to RFC and default time formats..) +const shortForm = "2006-01-02" + +// IsBefore checker verifies the specified value is before the specified time. +// It is exclusive. +// +// c.Assert(myTime, IsBefore, theTime, check.Commentf("bouuuhhh")) +// +var IsBefore check.Checker = &isBeforeChecker{ + &check.CheckerInfo{ + Name: "IsBefore", + Params: []string{"obtained", "expected"}, + }, +} + +type isBeforeChecker struct { + *check.CheckerInfo +} + +func (checker *isBeforeChecker) Check(params []interface{}, names []string) (bool, string) { + return isBefore(params[0], params[1]) +} + +func isBefore(value, t interface{}) (bool, string) { + tTime, ok := parseTime(t) + if !ok { + return false, "expected must be a Time struct, or parseable." + } + valueTime, valueIsTime := parseTime(value) + if valueIsTime { + return valueTime.Before(tTime), "" + } + return false, "obtained value is not a time.Time struct or parseable as a time." +} + +// IsAfter checker verifies the specified value is before the specified time. +// It is exclusive. +// +// c.Assert(myTime, IsAfter, theTime, check.Commentf("bouuuhhh")) +// +var IsAfter check.Checker = &isAfterChecker{ + &check.CheckerInfo{ + Name: "IsAfter", + Params: []string{"obtained", "expected"}, + }, +} + +type isAfterChecker struct { + *check.CheckerInfo +} + +func (checker *isAfterChecker) Check(params []interface{}, names []string) (bool, string) { + return isAfter(params[0], params[1]) +} + +func isAfter(value, t interface{}) (bool, string) { + tTime, ok := parseTime(t) + if !ok { + return false, "expected must be a Time struct, or parseable." + } + valueTime, valueIsTime := parseTime(value) + if valueIsTime { + return valueTime.After(tTime), "" + } + return false, "obtained value is not a time.Time struct or parseable as a time." +} + +// IsBetween checker verifies the specified time is between the specified start +// and end. It's exclusive so if the specified time is at the tip of the interval. +// +// c.Assert(myTime, IsBetween, startTime, endTime, check.Commentf("bouuuhhh")) +// +var IsBetween check.Checker = &isBetweenChecker{ + &check.CheckerInfo{ + Name: "IsBetween", + Params: []string{"obtained", "start", "end"}, + }, +} + +type isBetweenChecker struct { + *check.CheckerInfo +} + +func (checker *isBetweenChecker) Check(params []interface{}, names []string) (bool, string) { + return isBetween(params[0], params[1], params[2]) +} + +func isBetween(value, start, end interface{}) (bool, string) { + startTime, ok := parseTime(start) + if !ok { + return false, "start must be a Time struct, or parseable." + } + endTime, ok := parseTime(end) + if !ok { + return false, "end must be a Time struct, or parseable." + } + valueTime, valueIsTime := parseTime(value) + if valueIsTime { + return valueTime.After(startTime) && valueTime.Before(endTime), "" + } + return false, "obtained value is not a time.Time struct or parseable as a time." +} + +// TimeEquals checker verifies the specified time is the equal to the expected +// time. +// +// c.Assert(myTime, TimeEquals, expected, check.Commentf("bouhhh")) +// +// It's possible to ignore some part of the time (like hours, minutes, etc..) using +// the TimeIgnore checker with it. +// +// c.Assert(myTime, TimeIgnore(TimeEquals, time.Hour), expected, check.Commentf("... bouh..")) +// +var TimeEquals check.Checker = &timeEqualsChecker{ + &check.CheckerInfo{ + Name: "TimeEquals", + Params: []string{"obtained", "expected"}, + }, +} + +type timeEqualsChecker struct { + *check.CheckerInfo +} + +func (checker *timeEqualsChecker) Check(params []interface{}, names []string) (bool, string) { + return timeEquals(params[0], params[1]) +} + +func timeEquals(obtained, expected interface{}) (bool, string) { + expectedTime, ok := parseTime(expected) + if !ok { + return false, "expected must be a Time struct, or parseable." + } + valueTime, valueIsTime := parseTime(obtained) + if valueIsTime { + return valueTime.Equal(expectedTime), "" + } + return false, "obtained value is not a time.Time struct or parseable as a time." +} + +// TimeIgnore checker will ignore some part of the time on the encapsulated checker. +// +// c.Assert(myTime, TimeIgnore(IsBetween, time.Second), start, end) +// +// FIXME use interface{} for ignore (to enable "Month", .. +func TimeIgnore(checker check.Checker, ignore time.Duration) check.Checker { + return &timeIgnoreChecker{ + sub: checker, + ignore: ignore, + } +} + +type timeIgnoreChecker struct { + sub check.Checker + ignore time.Duration +} + +func (checker *timeIgnoreChecker) Info() *check.CheckerInfo { + info := *checker.sub.Info() + info.Name = fmt.Sprintf("TimeIgnore(%s, %v)", info.Name, checker.ignore) + return &info +} + +func (checker *timeIgnoreChecker) Check(params []interface{}, names []string) (bool, string) { + // Naive implementation : all params are supposed to be date + mParams := make([]interface{}, len(params)) + for index, param := range params { + paramTime, ok := parseTime(param) + if !ok { + return false, fmt.Sprintf("%s must be a Time struct, or parseable.", names[index]) + } + year := paramTime.Year() + month := paramTime.Month() + day := paramTime.Day() + hour := paramTime.Hour() + min := paramTime.Minute() + sec := paramTime.Second() + nsec := paramTime.Nanosecond() + location := paramTime.Location() + switch checker.ignore { + case time.Hour: + hour = 0 + fallthrough + case time.Minute: + min = 0 + fallthrough + case time.Second: + sec = 0 + fallthrough + case time.Millisecond: + fallthrough + case time.Microsecond: + fallthrough + case time.Nanosecond: + nsec = 0 + } + mParams[index] = time.Date(year, month, day, hour, min, sec, nsec, location) + } + return checker.sub.Check(mParams, names) +} + +func parseTime(datetime interface{}) (time.Time, bool) { + switch datetime.(type) { + case time.Time: + return datetime.(time.Time), true + case string: + return parseTimeAsString(datetime.(string)) + default: + if datetimeWithStr, ok := datetime.(fmt.Stringer); ok { + return parseTimeAsString(datetimeWithStr.String()) + } + return time.Time{}, false + } +} + +func parseTimeAsString(timeAsStr string) (time.Time, bool) { + forms := []string{shortForm, time.RFC3339, time.RFC3339Nano, time.RFC822, time.RFC822Z} + for _, form := range forms { + datetime, err := time.Parse(form, timeAsStr) + if err == nil { + return datetime, true + } + } + return time.Time{}, false +}