Vendor go-check in
Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
This commit is contained in:
		| @@ -52,6 +52,7 @@ clean() { | |||||||
| 	local packages=( | 	local packages=( | ||||||
| 		"${PROJECT}/containerd" # package main | 		"${PROJECT}/containerd" # package main | ||||||
| 		"${PROJECT}/ctr" # package main | 		"${PROJECT}/ctr" # package main | ||||||
|  | 		"${PROJECT}/integration-test" # package main | ||||||
| 	) | 	) | ||||||
| 	local platforms=( linux/amd64 linux/386 windows/amd64 windows/386 darwin/amd64 ) | 	local platforms=( linux/amd64 linux/386 windows/amd64 windows/386 darwin/amd64 ) | ||||||
| 	local buildTagCombos=( | 	local buildTagCombos=( | ||||||
| @@ -77,8 +78,8 @@ clean() { | |||||||
|  |  | ||||||
| 	echo -n 'pruning unused packages, ' | 	echo -n 'pruning unused packages, ' | ||||||
| 	findArgs=( | 	findArgs=( | ||||||
| 		# This directory contains only .c and .h files which are necessary | 		# for some reason go list doesn't detect this as a dependency | ||||||
| 		-path vendor/src/github.com/mattn/go-sqlite3/code | 		-path vendor/src/github.com/vdemeester/shakers | ||||||
| 	) | 	) | ||||||
| 	for import in "${imports[@]}"; do | 	for import in "${imports[@]}"; do | ||||||
| 		[ "${#findArgs[@]}" -eq 0 ] || findArgs+=( -or ) | 		[ "${#findArgs[@]}" -eq 0 ] || findArgs+=( -or ) | ||||||
|   | |||||||
| @@ -25,4 +25,7 @@ clone git golang.org/x/net 991d3e32f76f19ee6d9caadb3a22eae8d23315f7 https://gith | |||||||
| clone git google.golang.org/grpc a22b6611561e9f0a3e0919690dd2caf48f14c517 https://github.com/grpc/grpc-go.git | clone git google.golang.org/grpc a22b6611561e9f0a3e0919690dd2caf48f14c517 https://github.com/grpc/grpc-go.git | ||||||
| clone git github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c226cfc6a1 | clone git github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c226cfc6a1 | ||||||
|  |  | ||||||
|  | clone git github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 | ||||||
|  | clone git github.com/go-check/check a625211d932a2a643d0d17352095f03fb7774663 https://github.com/cpuguy83/check.git | ||||||
|  |  | ||||||
| clean | clean | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								vendor/src/github.com/docker/docker/pkg/integration/checker/checker.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/src/github.com/docker/docker/pkg/integration/checker/checker.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | // Package checker provide Docker specific implementations of the go-check.Checker interface. | ||||||
|  | package checker | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"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 | ||||||
|  | 	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 | ||||||
|  |  | ||||||
|  | 	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 | ||||||
|  | ) | ||||||
							
								
								
									
										4
									
								
								vendor/src/github.com/go-check/check/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								vendor/src/github.com/go-check/check/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | _* | ||||||
|  | *.swp | ||||||
|  | *.[568] | ||||||
|  | [568].out | ||||||
							
								
								
									
										10
									
								
								vendor/src/github.com/go-check/check/.travis.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								vendor/src/github.com/go-check/check/.travis.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | language: go | ||||||
|  | go: | ||||||
|  |   - 1.5 | ||||||
|  |   - tip | ||||||
|  | script: | ||||||
|  |   - go get -u github.com/golang/lint/golint | ||||||
|  |   - # go vet ./... | ||||||
|  |   - # test -z "$(golint ./... | tee /dev/stderr)" | ||||||
|  |   - # test -z "$(gofmt -s -l . | tee /dev/stderr)" | ||||||
|  |   - go test -v ./... | ||||||
							
								
								
									
										25
									
								
								vendor/src/github.com/go-check/check/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/src/github.com/go-check/check/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | |||||||
|  | Gocheck - A rich testing framework for Go | ||||||
|  |   | ||||||
|  | Copyright (c) 2010-2013 Gustavo Niemeyer <gustavo@niemeyer.net> | ||||||
|  |  | ||||||
|  | All rights reserved. | ||||||
|  |  | ||||||
|  | Redistribution and use in source and binary forms, with or without | ||||||
|  | modification, are permitted provided that the following conditions are met:  | ||||||
|  |  | ||||||
|  | 1. Redistributions of source code must retain the above copyright notice, this | ||||||
|  |    list of conditions and the following disclaimer.  | ||||||
|  | 2. 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.  | ||||||
|  |  | ||||||
|  | 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. | ||||||
							
								
								
									
										10
									
								
								vendor/src/github.com/go-check/check/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								vendor/src/github.com/go-check/check/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | Go-check | ||||||
|  | ======== | ||||||
|  |  | ||||||
|  | This is a fork of https://github.com/go-check/check | ||||||
|  |  | ||||||
|  | The intention of this fork is not to change any of the original behavior, but add | ||||||
|  | some specific behaviors needed for some of my projects already using this test suite. | ||||||
|  | For documentation on the main behavior of go-check see the aforementioned repo. | ||||||
|  |  | ||||||
|  | The original branch is intact at `orig_v1` | ||||||
							
								
								
									
										2
									
								
								vendor/src/github.com/go-check/check/TODO
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								vendor/src/github.com/go-check/check/TODO
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | - Assert(slice, Contains, item) | ||||||
|  | - Parallel test support | ||||||
							
								
								
									
										187
									
								
								vendor/src/github.com/go-check/check/benchmark.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								vendor/src/github.com/go-check/check/benchmark.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,187 @@ | |||||||
|  | // 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 | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"runtime" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | var memStats runtime.MemStats | ||||||
|  |  | ||||||
|  | // testingB is a type passed to Benchmark functions to manage benchmark | ||||||
|  | // timing and to specify the number of iterations to run. | ||||||
|  | type timer struct { | ||||||
|  | 	start     time.Time // Time test or benchmark started | ||||||
|  | 	duration  time.Duration | ||||||
|  | 	N         int | ||||||
|  | 	bytes     int64 | ||||||
|  | 	timerOn   bool | ||||||
|  | 	benchTime time.Duration | ||||||
|  | 	// The initial states of memStats.Mallocs and memStats.TotalAlloc. | ||||||
|  | 	startAllocs uint64 | ||||||
|  | 	startBytes  uint64 | ||||||
|  | 	// The net total of this test after being run. | ||||||
|  | 	netAllocs uint64 | ||||||
|  | 	netBytes  uint64 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // StartTimer starts timing a test. This function is called automatically | ||||||
|  | // before a benchmark starts, but it can also used to resume timing after | ||||||
|  | // a call to StopTimer. | ||||||
|  | func (c *C) StartTimer() { | ||||||
|  | 	if !c.timerOn { | ||||||
|  | 		c.start = time.Now() | ||||||
|  | 		c.timerOn = true | ||||||
|  |  | ||||||
|  | 		runtime.ReadMemStats(&memStats) | ||||||
|  | 		c.startAllocs = memStats.Mallocs | ||||||
|  | 		c.startBytes = memStats.TotalAlloc | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // StopTimer stops timing a test. This can be used to pause the timer | ||||||
|  | // while performing complex initialization that you don't | ||||||
|  | // want to measure. | ||||||
|  | func (c *C) StopTimer() { | ||||||
|  | 	if c.timerOn { | ||||||
|  | 		c.duration += time.Now().Sub(c.start) | ||||||
|  | 		c.timerOn = false | ||||||
|  | 		runtime.ReadMemStats(&memStats) | ||||||
|  | 		c.netAllocs += memStats.Mallocs - c.startAllocs | ||||||
|  | 		c.netBytes += memStats.TotalAlloc - c.startBytes | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ResetTimer sets the elapsed benchmark time to zero. | ||||||
|  | // It does not affect whether the timer is running. | ||||||
|  | func (c *C) ResetTimer() { | ||||||
|  | 	if c.timerOn { | ||||||
|  | 		c.start = time.Now() | ||||||
|  | 		runtime.ReadMemStats(&memStats) | ||||||
|  | 		c.startAllocs = memStats.Mallocs | ||||||
|  | 		c.startBytes = memStats.TotalAlloc | ||||||
|  | 	} | ||||||
|  | 	c.duration = 0 | ||||||
|  | 	c.netAllocs = 0 | ||||||
|  | 	c.netBytes = 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SetBytes informs the number of bytes that the benchmark processes | ||||||
|  | // on each iteration. If this is called in a benchmark it will also | ||||||
|  | // report MB/s. | ||||||
|  | func (c *C) SetBytes(n int64) { | ||||||
|  | 	c.bytes = n | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) nsPerOp() int64 { | ||||||
|  | 	if c.N <= 0 { | ||||||
|  | 		return 0 | ||||||
|  | 	} | ||||||
|  | 	return c.duration.Nanoseconds() / int64(c.N) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) mbPerSec() float64 { | ||||||
|  | 	if c.bytes <= 0 || c.duration <= 0 || c.N <= 0 { | ||||||
|  | 		return 0 | ||||||
|  | 	} | ||||||
|  | 	return (float64(c.bytes) * float64(c.N) / 1e6) / c.duration.Seconds() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) timerString() string { | ||||||
|  | 	if c.N <= 0 { | ||||||
|  | 		return fmt.Sprintf("%3.3fs", float64(c.duration.Nanoseconds())/1e9) | ||||||
|  | 	} | ||||||
|  | 	mbs := c.mbPerSec() | ||||||
|  | 	mb := "" | ||||||
|  | 	if mbs != 0 { | ||||||
|  | 		mb = fmt.Sprintf("\t%7.2f MB/s", mbs) | ||||||
|  | 	} | ||||||
|  | 	nsop := c.nsPerOp() | ||||||
|  | 	ns := fmt.Sprintf("%10d ns/op", nsop) | ||||||
|  | 	if c.N > 0 && nsop < 100 { | ||||||
|  | 		// The format specifiers here make sure that | ||||||
|  | 		// the ones digits line up for all three possible formats. | ||||||
|  | 		if nsop < 10 { | ||||||
|  | 			ns = fmt.Sprintf("%13.2f ns/op", float64(c.duration.Nanoseconds())/float64(c.N)) | ||||||
|  | 		} else { | ||||||
|  | 			ns = fmt.Sprintf("%12.1f ns/op", float64(c.duration.Nanoseconds())/float64(c.N)) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	memStats := "" | ||||||
|  | 	if c.benchMem { | ||||||
|  | 		allocedBytes := fmt.Sprintf("%8d B/op", int64(c.netBytes)/int64(c.N)) | ||||||
|  | 		allocs := fmt.Sprintf("%8d allocs/op", int64(c.netAllocs)/int64(c.N)) | ||||||
|  | 		memStats = fmt.Sprintf("\t%s\t%s", allocedBytes, allocs) | ||||||
|  | 	} | ||||||
|  | 	return fmt.Sprintf("%8d\t%s%s%s", c.N, ns, mb, memStats) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func min(x, y int) int { | ||||||
|  | 	if x > y { | ||||||
|  | 		return y | ||||||
|  | 	} | ||||||
|  | 	return x | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func max(x, y int) int { | ||||||
|  | 	if x < y { | ||||||
|  | 		return y | ||||||
|  | 	} | ||||||
|  | 	return x | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // roundDown10 rounds a number down to the nearest power of 10. | ||||||
|  | func roundDown10(n int) int { | ||||||
|  | 	var tens = 0 | ||||||
|  | 	// tens = floor(log_10(n)) | ||||||
|  | 	for n > 10 { | ||||||
|  | 		n = n / 10 | ||||||
|  | 		tens++ | ||||||
|  | 	} | ||||||
|  | 	// result = 10^tens | ||||||
|  | 	result := 1 | ||||||
|  | 	for i := 0; i < tens; i++ { | ||||||
|  | 		result *= 10 | ||||||
|  | 	} | ||||||
|  | 	return result | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // roundUp rounds x up to a number of the form [1eX, 2eX, 5eX]. | ||||||
|  | func roundUp(n int) int { | ||||||
|  | 	base := roundDown10(n) | ||||||
|  | 	if n < (2 * base) { | ||||||
|  | 		return 2 * base | ||||||
|  | 	} | ||||||
|  | 	if n < (5 * base) { | ||||||
|  | 		return 5 * base | ||||||
|  | 	} | ||||||
|  | 	return 10 * base | ||||||
|  | } | ||||||
							
								
								
									
										892
									
								
								vendor/src/github.com/go-check/check/check.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										892
									
								
								vendor/src/github.com/go-check/check/check.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,892 @@ | |||||||
|  | // Package check is a rich testing extension for Go's testing package. | ||||||
|  | // | ||||||
|  | // For details about the project, see: | ||||||
|  | // | ||||||
|  | //     http://labix.org/gocheck | ||||||
|  | // | ||||||
|  | package check | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"errors" | ||||||
|  | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"math/rand" | ||||||
|  | 	"os" | ||||||
|  | 	"path" | ||||||
|  | 	"path/filepath" | ||||||
|  | 	"reflect" | ||||||
|  | 	"regexp" | ||||||
|  | 	"runtime" | ||||||
|  | 	"strconv" | ||||||
|  | 	"strings" | ||||||
|  | 	"sync" | ||||||
|  | 	"sync/atomic" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Internal type which deals with suite method calling. | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	fixtureKd = iota | ||||||
|  | 	testKd | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type funcKind int | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	succeededSt = iota | ||||||
|  | 	failedSt | ||||||
|  | 	skippedSt | ||||||
|  | 	panickedSt | ||||||
|  | 	fixturePanickedSt | ||||||
|  | 	missedSt | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type funcStatus uint32 | ||||||
|  |  | ||||||
|  | // A method value can't reach its own Method structure. | ||||||
|  | type methodType struct { | ||||||
|  | 	reflect.Value | ||||||
|  | 	Info reflect.Method | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func newMethod(receiver reflect.Value, i int) *methodType { | ||||||
|  | 	return &methodType{receiver.Method(i), receiver.Type().Method(i)} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (method *methodType) PC() uintptr { | ||||||
|  | 	return method.Info.Func.Pointer() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (method *methodType) suiteName() string { | ||||||
|  | 	t := method.Info.Type.In(0) | ||||||
|  | 	if t.Kind() == reflect.Ptr { | ||||||
|  | 		t = t.Elem() | ||||||
|  | 	} | ||||||
|  | 	return t.Name() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (method *methodType) String() string { | ||||||
|  | 	return method.suiteName() + "." + method.Info.Name | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (method *methodType) matches(re *regexp.Regexp) bool { | ||||||
|  | 	return (re.MatchString(method.Info.Name) || | ||||||
|  | 		re.MatchString(method.suiteName()) || | ||||||
|  | 		re.MatchString(method.String())) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type C struct { | ||||||
|  | 	method    *methodType | ||||||
|  | 	kind      funcKind | ||||||
|  | 	testName  string | ||||||
|  | 	_status   funcStatus | ||||||
|  | 	logb      *logger | ||||||
|  | 	logw      io.Writer | ||||||
|  | 	done      chan *C | ||||||
|  | 	reason    string | ||||||
|  | 	mustFail  bool | ||||||
|  | 	tempDir   *tempDir | ||||||
|  | 	benchMem  bool | ||||||
|  | 	startTime time.Time | ||||||
|  | 	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() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // logger is a concurrency safe byte.Buffer | ||||||
|  | type logger struct { | ||||||
|  | 	sync.Mutex | ||||||
|  | 	writer bytes.Buffer | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (l *logger) Write(buf []byte) (int, error) { | ||||||
|  | 	l.Lock() | ||||||
|  | 	defer l.Unlock() | ||||||
|  | 	return l.writer.Write(buf) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (l *logger) WriteTo(w io.Writer) (int64, error) { | ||||||
|  | 	l.Lock() | ||||||
|  | 	defer l.Unlock() | ||||||
|  | 	return l.writer.WriteTo(w) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (l *logger) String() string { | ||||||
|  | 	l.Lock() | ||||||
|  | 	defer l.Unlock() | ||||||
|  | 	return l.writer.String() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Handling of temporary files and directories. | ||||||
|  |  | ||||||
|  | type tempDir struct { | ||||||
|  | 	sync.Mutex | ||||||
|  | 	path    string | ||||||
|  | 	counter int | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (td *tempDir) newPath() string { | ||||||
|  | 	td.Lock() | ||||||
|  | 	defer td.Unlock() | ||||||
|  | 	if td.path == "" { | ||||||
|  | 		var err error | ||||||
|  | 		for i := 0; i != 100; i++ { | ||||||
|  | 			path := fmt.Sprintf("%s%ccheck-%d", os.TempDir(), os.PathSeparator, rand.Int()) | ||||||
|  | 			if err = os.Mkdir(path, 0700); err == nil { | ||||||
|  | 				td.path = path | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if td.path == "" { | ||||||
|  | 			panic("Couldn't create temporary directory: " + err.Error()) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	result := filepath.Join(td.path, strconv.Itoa(td.counter)) | ||||||
|  | 	td.counter += 1 | ||||||
|  | 	return result | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (td *tempDir) removeAll() { | ||||||
|  | 	td.Lock() | ||||||
|  | 	defer td.Unlock() | ||||||
|  | 	if td.path != "" { | ||||||
|  | 		err := os.RemoveAll(td.path) | ||||||
|  | 		if err != nil { | ||||||
|  | 			fmt.Fprintf(os.Stderr, "WARNING: Error cleaning up temporaries: "+err.Error()) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Create a new temporary directory which is automatically removed after | ||||||
|  | // the suite finishes running. | ||||||
|  | func (c *C) MkDir() string { | ||||||
|  | 	path := c.tempDir.newPath() | ||||||
|  | 	if err := os.Mkdir(path, 0700); err != nil { | ||||||
|  | 		panic(fmt.Sprintf("Couldn't create temporary directory %s: %s", path, err.Error())) | ||||||
|  | 	} | ||||||
|  | 	return path | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Low-level logging functions. | ||||||
|  |  | ||||||
|  | func (c *C) log(args ...interface{}) { | ||||||
|  | 	c.writeLog([]byte(fmt.Sprint(args...) + "\n")) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) logf(format string, args ...interface{}) { | ||||||
|  | 	c.writeLog([]byte(fmt.Sprintf(format+"\n", args...))) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) logNewLine() { | ||||||
|  | 	c.writeLog([]byte{'\n'}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) writeLog(buf []byte) { | ||||||
|  | 	c.logb.Write(buf) | ||||||
|  | 	if c.logw != nil { | ||||||
|  | 		c.logw.Write(buf) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func hasStringOrError(x interface{}) (ok bool) { | ||||||
|  | 	_, ok = x.(fmt.Stringer) | ||||||
|  | 	if ok { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	_, ok = x.(error) | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) logValue(label string, value interface{}) { | ||||||
|  | 	if label == "" { | ||||||
|  | 		if hasStringOrError(value) { | ||||||
|  | 			c.logf("... %#v (%q)", value, value) | ||||||
|  | 		} else { | ||||||
|  | 			c.logf("... %#v", value) | ||||||
|  | 		} | ||||||
|  | 	} else if value == nil { | ||||||
|  | 		c.logf("... %s = nil", label) | ||||||
|  | 	} else { | ||||||
|  | 		if hasStringOrError(value) { | ||||||
|  | 			fv := fmt.Sprintf("%#v", value) | ||||||
|  | 			qv := fmt.Sprintf("%q", value) | ||||||
|  | 			if fv != qv { | ||||||
|  | 				c.logf("... %s %s = %s (%s)", label, reflect.TypeOf(value), fv, qv) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if s, ok := value.(string); ok && isMultiLine(s) { | ||||||
|  | 			c.logf(`... %s %s = "" +`, label, reflect.TypeOf(value)) | ||||||
|  | 			c.logMultiLine(s) | ||||||
|  | 		} else { | ||||||
|  | 			c.logf("... %s %s = %#v", label, reflect.TypeOf(value), value) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) logMultiLine(s string) { | ||||||
|  | 	b := make([]byte, 0, len(s)*2) | ||||||
|  | 	i := 0 | ||||||
|  | 	n := len(s) | ||||||
|  | 	for i < n { | ||||||
|  | 		j := i + 1 | ||||||
|  | 		for j < n && s[j-1] != '\n' { | ||||||
|  | 			j++ | ||||||
|  | 		} | ||||||
|  | 		b = append(b, "...     "...) | ||||||
|  | 		b = strconv.AppendQuote(b, s[i:j]) | ||||||
|  | 		if j < n { | ||||||
|  | 			b = append(b, " +"...) | ||||||
|  | 		} | ||||||
|  | 		b = append(b, '\n') | ||||||
|  | 		i = j | ||||||
|  | 	} | ||||||
|  | 	c.writeLog(b) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func isMultiLine(s string) bool { | ||||||
|  | 	for i := 0; i+1 < len(s); i++ { | ||||||
|  | 		if s[i] == '\n' { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) logString(issue string) { | ||||||
|  | 	c.log("... ", issue) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) logCaller(skip int) { | ||||||
|  | 	// This is a bit heavier than it ought to be. | ||||||
|  | 	skip += 1 // Our own frame. | ||||||
|  | 	pc, callerFile, callerLine, ok := runtime.Caller(skip) | ||||||
|  | 	if !ok { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	var testFile string | ||||||
|  | 	var testLine int | ||||||
|  | 	testFunc := runtime.FuncForPC(c.method.PC()) | ||||||
|  | 	if runtime.FuncForPC(pc) != testFunc { | ||||||
|  | 		for { | ||||||
|  | 			skip += 1 | ||||||
|  | 			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 | ||||||
|  | 				// the "internal" line is helpful when debugging. | ||||||
|  | 				if runtime.FuncForPC(pc) == testFunc { | ||||||
|  | 					testFile, testLine = file, line | ||||||
|  | 					break | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if testFile != "" && (testFile != callerFile || testLine != callerLine) { | ||||||
|  | 		c.logCode(testFile, testLine) | ||||||
|  | 	} | ||||||
|  | 	c.logCode(callerFile, callerLine) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) logCode(path string, line int) { | ||||||
|  | 	c.logf("%s:%d:", nicePath(path), line) | ||||||
|  | 	code, err := printLine(path, line) | ||||||
|  | 	if code == "" { | ||||||
|  | 		code = "..." // XXX Open the file and take the raw line. | ||||||
|  | 		if err != nil { | ||||||
|  | 			code += err.Error() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	c.log(indent(code, "    ")) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | var valueGo = filepath.Join("reflect", "value.go") | ||||||
|  | var asmGo = filepath.Join("runtime", "asm_") | ||||||
|  |  | ||||||
|  | func (c *C) logPanic(skip int, value interface{}) { | ||||||
|  | 	skip++ // Our own frame. | ||||||
|  | 	initialSkip := skip | ||||||
|  | 	for ; ; skip++ { | ||||||
|  | 		if pc, file, line, ok := runtime.Caller(skip); ok { | ||||||
|  | 			if skip == initialSkip { | ||||||
|  | 				c.logf("... Panic: %s (PC=0x%X)\n", value, pc) | ||||||
|  | 			} | ||||||
|  | 			name := niceFuncName(pc) | ||||||
|  | 			path := nicePath(file) | ||||||
|  | 			if strings.Contains(path, "/gopkg.in/check.v") { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			if name == "Value.call" && strings.HasSuffix(path, valueGo) { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			if (name == "call16" || name == "call32") && strings.Contains(path, asmGo) { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			c.logf("%s:%d\n  in %s", nicePath(file), line, name) | ||||||
|  | 		} else { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) logSoftPanic(issue string) { | ||||||
|  | 	c.log("... Panic: ", issue) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) logArgPanic(method *methodType, expectedType string) { | ||||||
|  | 	c.logf("... Panic: %s argument should be %s", | ||||||
|  | 		niceFuncName(method.PC()), expectedType) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Some simple formatting helpers. | ||||||
|  |  | ||||||
|  | var initWD, initWDErr = os.Getwd() | ||||||
|  |  | ||||||
|  | func init() { | ||||||
|  | 	if initWDErr == nil { | ||||||
|  | 		initWD = strings.Replace(initWD, "\\", "/", -1) + "/" | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func nicePath(path string) string { | ||||||
|  | 	if initWDErr == nil { | ||||||
|  | 		if strings.HasPrefix(path, initWD) { | ||||||
|  | 			return path[len(initWD):] | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return path | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func niceFuncPath(pc uintptr) string { | ||||||
|  | 	function := runtime.FuncForPC(pc) | ||||||
|  | 	if function != nil { | ||||||
|  | 		filename, line := function.FileLine(pc) | ||||||
|  | 		return fmt.Sprintf("%s:%d", nicePath(filename), line) | ||||||
|  | 	} | ||||||
|  | 	return "<unknown path>" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func niceFuncName(pc uintptr) string { | ||||||
|  | 	function := runtime.FuncForPC(pc) | ||||||
|  | 	if function != nil { | ||||||
|  | 		name := path.Base(function.Name()) | ||||||
|  | 		if i := strings.Index(name, "."); i > 0 { | ||||||
|  | 			name = name[i+1:] | ||||||
|  | 		} | ||||||
|  | 		if strings.HasPrefix(name, "(*") { | ||||||
|  | 			if i := strings.Index(name, ")"); i > 0 { | ||||||
|  | 				name = name[2:i] + name[i+1:] | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if i := strings.LastIndex(name, ".*"); i != -1 { | ||||||
|  | 			name = name[:i] + "." + name[i+2:] | ||||||
|  | 		} | ||||||
|  | 		if i := strings.LastIndex(name, "·"); i != -1 { | ||||||
|  | 			name = name[:i] + "." + name[i+2:] | ||||||
|  | 		} | ||||||
|  | 		return name | ||||||
|  | 	} | ||||||
|  | 	return "<unknown function>" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Result tracker to aggregate call results. | ||||||
|  |  | ||||||
|  | type Result struct { | ||||||
|  | 	Succeeded        int | ||||||
|  | 	Failed           int | ||||||
|  | 	Skipped          int | ||||||
|  | 	Panicked         int | ||||||
|  | 	FixturePanicked  int | ||||||
|  | 	ExpectedFailures int | ||||||
|  | 	Missed           int    // Not even tried to run, related to a panic in the fixture. | ||||||
|  | 	RunError         error  // Houston, we've got a problem. | ||||||
|  | 	WorkDir          string // If KeepWorkDir is true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type resultTracker struct { | ||||||
|  | 	result          Result | ||||||
|  | 	_lastWasProblem bool | ||||||
|  | 	_waiting        int | ||||||
|  | 	_missed         int | ||||||
|  | 	_expectChan     chan *C | ||||||
|  | 	_doneChan       chan *C | ||||||
|  | 	_stopChan       chan bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func newResultTracker() *resultTracker { | ||||||
|  | 	return &resultTracker{_expectChan: make(chan *C), // Synchronous | ||||||
|  | 		_doneChan: make(chan *C, 32), // Asynchronous | ||||||
|  | 		_stopChan: make(chan bool)}   // Synchronous | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tracker *resultTracker) start() { | ||||||
|  | 	go tracker._loopRoutine() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tracker *resultTracker) waitAndStop() { | ||||||
|  | 	<-tracker._stopChan | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tracker *resultTracker) expectCall(c *C) { | ||||||
|  | 	tracker._expectChan <- c | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tracker *resultTracker) callDone(c *C) { | ||||||
|  | 	tracker._doneChan <- c | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (tracker *resultTracker) _loopRoutine() { | ||||||
|  | 	for { | ||||||
|  | 		var c *C | ||||||
|  | 		if tracker._waiting > 0 { | ||||||
|  | 			// Calls still running. Can't stop. | ||||||
|  | 			select { | ||||||
|  | 			// XXX Reindent this (not now to make diff clear) | ||||||
|  | 			case c = <-tracker._expectChan: | ||||||
|  | 				tracker._waiting += 1 | ||||||
|  | 			case c = <-tracker._doneChan: | ||||||
|  | 				tracker._waiting -= 1 | ||||||
|  | 				switch c.status() { | ||||||
|  | 				case succeededSt: | ||||||
|  | 					if c.kind == testKd { | ||||||
|  | 						if c.mustFail { | ||||||
|  | 							tracker.result.ExpectedFailures++ | ||||||
|  | 						} else { | ||||||
|  | 							tracker.result.Succeeded++ | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				case failedSt: | ||||||
|  | 					tracker.result.Failed++ | ||||||
|  | 				case panickedSt: | ||||||
|  | 					if c.kind == fixtureKd { | ||||||
|  | 						tracker.result.FixturePanicked++ | ||||||
|  | 					} else { | ||||||
|  | 						tracker.result.Panicked++ | ||||||
|  | 					} | ||||||
|  | 				case fixturePanickedSt: | ||||||
|  | 					// Track it as missed, since the panic | ||||||
|  | 					// was on the fixture, not on the test. | ||||||
|  | 					tracker.result.Missed++ | ||||||
|  | 				case missedSt: | ||||||
|  | 					tracker.result.Missed++ | ||||||
|  | 				case skippedSt: | ||||||
|  | 					if c.kind == testKd { | ||||||
|  | 						tracker.result.Skipped++ | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			// No calls.  Can stop, but no done calls here. | ||||||
|  | 			select { | ||||||
|  | 			case tracker._stopChan <- true: | ||||||
|  | 				return | ||||||
|  | 			case c = <-tracker._expectChan: | ||||||
|  | 				tracker._waiting += 1 | ||||||
|  | 			case c = <-tracker._doneChan: | ||||||
|  | 				panic("Tracker got an unexpected done call.") | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // The underlying suite runner. | ||||||
|  |  | ||||||
|  | type suiteRunner struct { | ||||||
|  | 	suite                     interface{} | ||||||
|  | 	setUpSuite, tearDownSuite *methodType | ||||||
|  | 	setUpTest, tearDownTest   *methodType | ||||||
|  | 	tests                     []*methodType | ||||||
|  | 	tracker                   *resultTracker | ||||||
|  | 	tempDir                   *tempDir | ||||||
|  | 	keepDir                   bool | ||||||
|  | 	output                    *outputWriter | ||||||
|  | 	reportedProblemLast       bool | ||||||
|  | 	benchTime                 time.Duration | ||||||
|  | 	benchMem                  bool | ||||||
|  | 	checkTimeout              time.Duration | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type RunConf struct { | ||||||
|  | 	Output        io.Writer | ||||||
|  | 	Stream        bool | ||||||
|  | 	Verbose       bool | ||||||
|  | 	Filter        string | ||||||
|  | 	Benchmark     bool | ||||||
|  | 	BenchmarkTime time.Duration // Defaults to 1 second | ||||||
|  | 	BenchmarkMem  bool | ||||||
|  | 	KeepWorkDir   bool | ||||||
|  | 	CheckTimeout  time.Duration | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Create a new suiteRunner able to run all methods in the given suite. | ||||||
|  | func newSuiteRunner(suite interface{}, runConf *RunConf) *suiteRunner { | ||||||
|  | 	var conf RunConf | ||||||
|  | 	if runConf != nil { | ||||||
|  | 		conf = *runConf | ||||||
|  | 	} | ||||||
|  | 	if conf.Output == nil { | ||||||
|  | 		conf.Output = os.Stdout | ||||||
|  | 	} | ||||||
|  | 	if conf.Benchmark { | ||||||
|  | 		conf.Verbose = true | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	suiteType := reflect.TypeOf(suite) | ||||||
|  | 	suiteNumMethods := suiteType.NumMethod() | ||||||
|  | 	suiteValue := reflect.ValueOf(suite) | ||||||
|  |  | ||||||
|  | 	runner := &suiteRunner{ | ||||||
|  | 		suite:        suite, | ||||||
|  | 		output:       newOutputWriter(conf.Output, conf.Stream, conf.Verbose), | ||||||
|  | 		tracker:      newResultTracker(), | ||||||
|  | 		benchTime:    conf.BenchmarkTime, | ||||||
|  | 		benchMem:     conf.BenchmarkMem, | ||||||
|  | 		tempDir:      &tempDir{}, | ||||||
|  | 		keepDir:      conf.KeepWorkDir, | ||||||
|  | 		tests:        make([]*methodType, 0, suiteNumMethods), | ||||||
|  | 		checkTimeout: conf.CheckTimeout, | ||||||
|  | 	} | ||||||
|  | 	if runner.benchTime == 0 { | ||||||
|  | 		runner.benchTime = 1 * time.Second | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var filterRegexp *regexp.Regexp | ||||||
|  | 	if conf.Filter != "" { | ||||||
|  | 		if regexp, err := regexp.Compile(conf.Filter); err != nil { | ||||||
|  | 			msg := "Bad filter expression: " + err.Error() | ||||||
|  | 			runner.tracker.result.RunError = errors.New(msg) | ||||||
|  | 			return runner | ||||||
|  | 		} else { | ||||||
|  | 			filterRegexp = regexp | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for i := 0; i != suiteNumMethods; i++ { | ||||||
|  | 		method := newMethod(suiteValue, i) | ||||||
|  | 		switch method.Info.Name { | ||||||
|  | 		case "SetUpSuite": | ||||||
|  | 			runner.setUpSuite = method | ||||||
|  | 		case "TearDownSuite": | ||||||
|  | 			runner.tearDownSuite = method | ||||||
|  | 		case "SetUpTest": | ||||||
|  | 			runner.setUpTest = method | ||||||
|  | 		case "TearDownTest": | ||||||
|  | 			runner.tearDownTest = method | ||||||
|  | 		default: | ||||||
|  | 			prefix := "Test" | ||||||
|  | 			if conf.Benchmark { | ||||||
|  | 				prefix = "Benchmark" | ||||||
|  | 			} | ||||||
|  | 			if !strings.HasPrefix(method.Info.Name, prefix) { | ||||||
|  | 				continue | ||||||
|  | 			} | ||||||
|  | 			if filterRegexp == nil || method.matches(filterRegexp) { | ||||||
|  | 				runner.tests = append(runner.tests, method) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return runner | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Run all methods in the given suite. | ||||||
|  | func (runner *suiteRunner) run() *Result { | ||||||
|  | 	if runner.tracker.result.RunError == nil && len(runner.tests) > 0 { | ||||||
|  | 		runner.tracker.start() | ||||||
|  | 		if runner.checkFixtureArgs() { | ||||||
|  | 			c := runner.runFixture(runner.setUpSuite, "", nil) | ||||||
|  | 			if c == nil || c.status() == succeededSt { | ||||||
|  | 				for i := 0; i != len(runner.tests); i++ { | ||||||
|  | 					c := runner.runTest(runner.tests[i]) | ||||||
|  | 					if c.status() == fixturePanickedSt { | ||||||
|  | 						runner.skipTests(missedSt, runner.tests[i+1:]) | ||||||
|  | 						break | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} else if c != nil && c.status() == skippedSt { | ||||||
|  | 				runner.skipTests(skippedSt, runner.tests) | ||||||
|  | 			} else { | ||||||
|  | 				runner.skipTests(missedSt, runner.tests) | ||||||
|  | 			} | ||||||
|  | 			runner.runFixture(runner.tearDownSuite, "", nil) | ||||||
|  | 		} else { | ||||||
|  | 			runner.skipTests(missedSt, runner.tests) | ||||||
|  | 		} | ||||||
|  | 		runner.tracker.waitAndStop() | ||||||
|  | 		if runner.keepDir { | ||||||
|  | 			runner.tracker.result.WorkDir = runner.tempDir.path | ||||||
|  | 		} else { | ||||||
|  | 			runner.tempDir.removeAll() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return &runner.tracker.result | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Create a call object with the given suite method, and fork a | ||||||
|  | // goroutine with the provided dispatcher for running it. | ||||||
|  | func (runner *suiteRunner) forkCall(method *methodType, kind funcKind, testName string, logb *logger, dispatcher func(c *C)) *C { | ||||||
|  | 	var logw io.Writer | ||||||
|  | 	if runner.output.Stream { | ||||||
|  | 		logw = runner.output | ||||||
|  | 	} | ||||||
|  | 	if logb == nil { | ||||||
|  | 		logb = new(logger) | ||||||
|  | 	} | ||||||
|  | 	c := &C{ | ||||||
|  | 		method:    method, | ||||||
|  | 		kind:      kind, | ||||||
|  | 		testName:  testName, | ||||||
|  | 		logb:      logb, | ||||||
|  | 		logw:      logw, | ||||||
|  | 		tempDir:   runner.tempDir, | ||||||
|  | 		done:      make(chan *C, 1), | ||||||
|  | 		timer:     timer{benchTime: runner.benchTime}, | ||||||
|  | 		startTime: time.Now(), | ||||||
|  | 		benchMem:  runner.benchMem, | ||||||
|  | 	} | ||||||
|  | 	runner.tracker.expectCall(c) | ||||||
|  | 	go (func() { | ||||||
|  | 		runner.reportCallStarted(c) | ||||||
|  | 		defer runner.callDone(c) | ||||||
|  | 		dispatcher(c) | ||||||
|  | 	})() | ||||||
|  | 	return c | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Same as forkCall(), but wait for call to finish before returning. | ||||||
|  | func (runner *suiteRunner) runFunc(method *methodType, kind funcKind, testName string, logb *logger, dispatcher func(c *C)) *C { | ||||||
|  | 	var timeout <-chan time.Time | ||||||
|  | 	if runner.checkTimeout != 0 { | ||||||
|  | 		timeout = time.After(runner.checkTimeout) | ||||||
|  | 	} | ||||||
|  | 	c := runner.forkCall(method, kind, testName, logb, dispatcher) | ||||||
|  | 	select { | ||||||
|  | 	case <-c.done: | ||||||
|  | 	case <-timeout: | ||||||
|  | 		panic(fmt.Sprintf("test timed out after %v", runner.checkTimeout)) | ||||||
|  | 	} | ||||||
|  | 	return c | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Handle a finished call.  If there were any panics, update the call status | ||||||
|  | // accordingly.  Then, mark the call as done and report to the tracker. | ||||||
|  | func (runner *suiteRunner) callDone(c *C) { | ||||||
|  | 	value := recover() | ||||||
|  | 	if value != nil { | ||||||
|  | 		switch v := value.(type) { | ||||||
|  | 		case *fixturePanic: | ||||||
|  | 			if v.status == skippedSt { | ||||||
|  | 				c.setStatus(skippedSt) | ||||||
|  | 			} else { | ||||||
|  | 				c.logSoftPanic("Fixture has panicked (see related PANIC)") | ||||||
|  | 				c.setStatus(fixturePanickedSt) | ||||||
|  | 			} | ||||||
|  | 		default: | ||||||
|  | 			c.logPanic(1, value) | ||||||
|  | 			c.setStatus(panickedSt) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if c.mustFail { | ||||||
|  | 		switch c.status() { | ||||||
|  | 		case failedSt: | ||||||
|  | 			c.setStatus(succeededSt) | ||||||
|  | 		case succeededSt: | ||||||
|  | 			c.setStatus(failedSt) | ||||||
|  | 			c.logString("Error: Test succeeded, but was expected to fail") | ||||||
|  | 			c.logString("Reason: " + c.reason) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	runner.reportCallDone(c) | ||||||
|  | 	c.done <- c | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Runs a fixture call synchronously.  The fixture will still be run in a | ||||||
|  | // goroutine like all suite methods, but this method will not return | ||||||
|  | // while the fixture goroutine is not done, because the fixture must be | ||||||
|  | // run in a desired order. | ||||||
|  | func (runner *suiteRunner) runFixture(method *methodType, testName string, logb *logger) *C { | ||||||
|  | 	if method != nil { | ||||||
|  | 		c := runner.runFunc(method, fixtureKd, testName, logb, func(c *C) { | ||||||
|  | 			c.ResetTimer() | ||||||
|  | 			c.StartTimer() | ||||||
|  | 			defer c.StopTimer() | ||||||
|  | 			c.method.Call([]reflect.Value{reflect.ValueOf(c)}) | ||||||
|  | 		}) | ||||||
|  | 		return c | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Run the fixture method with runFixture(), but panic with a fixturePanic{} | ||||||
|  | // in case the fixture method panics.  This makes it easier to track the | ||||||
|  | // fixture panic together with other call panics within forkTest(). | ||||||
|  | func (runner *suiteRunner) runFixtureWithPanic(method *methodType, testName string, logb *logger, skipped *bool) *C { | ||||||
|  | 	if skipped != nil && *skipped { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	c := runner.runFixture(method, testName, logb) | ||||||
|  | 	if c != nil && c.status() != succeededSt { | ||||||
|  | 		if skipped != nil { | ||||||
|  | 			*skipped = c.status() == skippedSt | ||||||
|  | 		} | ||||||
|  | 		panic(&fixturePanic{c.status(), method}) | ||||||
|  | 	} | ||||||
|  | 	return c | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type fixturePanic struct { | ||||||
|  | 	status funcStatus | ||||||
|  | 	method *methodType | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Run the suite test method, together with the test-specific fixture, | ||||||
|  | // asynchronously. | ||||||
|  | func (runner *suiteRunner) forkTest(method *methodType) *C { | ||||||
|  | 	testName := method.String() | ||||||
|  | 	return runner.forkCall(method, testKd, testName, nil, func(c *C) { | ||||||
|  | 		var skipped bool | ||||||
|  | 		defer runner.runFixtureWithPanic(runner.tearDownTest, testName, nil, &skipped) | ||||||
|  | 		defer c.StopTimer() | ||||||
|  | 		benchN := 1 | ||||||
|  | 		for { | ||||||
|  | 			runner.runFixtureWithPanic(runner.setUpTest, testName, c.logb, &skipped) | ||||||
|  | 			mt := c.method.Type() | ||||||
|  | 			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.setStatus(panickedSt) | ||||||
|  | 				c.logArgPanic(c.method, "*check.C") | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			if strings.HasPrefix(c.method.Info.Name, "Test") { | ||||||
|  | 				c.ResetTimer() | ||||||
|  | 				c.StartTimer() | ||||||
|  | 				c.method.Call([]reflect.Value{reflect.ValueOf(c)}) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			if !strings.HasPrefix(c.method.Info.Name, "Benchmark") { | ||||||
|  | 				panic("unexpected method prefix: " + c.method.Info.Name) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			runtime.GC() | ||||||
|  | 			c.N = benchN | ||||||
|  | 			c.ResetTimer() | ||||||
|  | 			c.StartTimer() | ||||||
|  | 			c.method.Call([]reflect.Value{reflect.ValueOf(c)}) | ||||||
|  | 			c.StopTimer() | ||||||
|  | 			if c.status() != succeededSt || c.duration >= c.benchTime || benchN >= 1e9 { | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			perOpN := int(1e9) | ||||||
|  | 			if c.nsPerOp() != 0 { | ||||||
|  | 				perOpN = int(c.benchTime.Nanoseconds() / c.nsPerOp()) | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Logic taken from the stock testing package: | ||||||
|  | 			// - Run more iterations than we think we'll need for a second (1.5x). | ||||||
|  | 			// - Don't grow too fast in case we had timing errors previously. | ||||||
|  | 			// - Be sure to run at least one more than last time. | ||||||
|  | 			benchN = max(min(perOpN+perOpN/2, 100*benchN), benchN+1) | ||||||
|  | 			benchN = roundUp(benchN) | ||||||
|  |  | ||||||
|  | 			skipped = true // Don't run the deferred one if this panics. | ||||||
|  | 			runner.runFixtureWithPanic(runner.tearDownTest, testName, nil, nil) | ||||||
|  | 			skipped = false | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Same as forkTest(), but wait for the test to finish before returning. | ||||||
|  | func (runner *suiteRunner) runTest(method *methodType) *C { | ||||||
|  | 	var timeout <-chan time.Time | ||||||
|  | 	if runner.checkTimeout != 0 { | ||||||
|  | 		timeout = time.After(runner.checkTimeout) | ||||||
|  | 	} | ||||||
|  | 	c := runner.forkTest(method) | ||||||
|  | 	select { | ||||||
|  | 	case <-c.done: | ||||||
|  | 	case <-timeout: | ||||||
|  | 		panic(fmt.Sprintf("test timed out after %v", runner.checkTimeout)) | ||||||
|  | 	} | ||||||
|  | 	return c | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Helper to mark tests as skipped or missed.  A bit heavy for what | ||||||
|  | // it does, but it enables homogeneous handling of tracking, including | ||||||
|  | // nice verbose output. | ||||||
|  | func (runner *suiteRunner) skipTests(status funcStatus, methods []*methodType) { | ||||||
|  | 	for _, method := range methods { | ||||||
|  | 		runner.runFunc(method, testKd, "", nil, func(c *C) { | ||||||
|  | 			c.setStatus(status) | ||||||
|  | 		}) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Verify if the fixture arguments are *check.C.  In case of errors, | ||||||
|  | // log the error as a panic in the fixture method call, and return false. | ||||||
|  | func (runner *suiteRunner) checkFixtureArgs() bool { | ||||||
|  | 	succeeded := true | ||||||
|  | 	argType := reflect.TypeOf(&C{}) | ||||||
|  | 	for _, method := range []*methodType{runner.setUpSuite, runner.tearDownSuite, runner.setUpTest, runner.tearDownTest} { | ||||||
|  | 		if method != nil { | ||||||
|  | 			mt := method.Type() | ||||||
|  | 			if mt.NumIn() != 1 || mt.In(0) != argType { | ||||||
|  | 				succeeded = false | ||||||
|  | 				runner.runFunc(method, fixtureKd, "", nil, func(c *C) { | ||||||
|  | 					c.logArgPanic(method, "*check.C") | ||||||
|  | 					c.setStatus(panickedSt) | ||||||
|  | 				}) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return succeeded | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (runner *suiteRunner) reportCallStarted(c *C) { | ||||||
|  | 	runner.output.WriteCallStarted("START", c) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (runner *suiteRunner) reportCallDone(c *C) { | ||||||
|  | 	runner.tracker.callDone(c) | ||||||
|  | 	switch c.status() { | ||||||
|  | 	case succeededSt: | ||||||
|  | 		if c.mustFail { | ||||||
|  | 			runner.output.WriteCallSuccess("FAIL EXPECTED", c) | ||||||
|  | 		} else { | ||||||
|  | 			runner.output.WriteCallSuccess("PASS", c) | ||||||
|  | 		} | ||||||
|  | 	case skippedSt: | ||||||
|  | 		runner.output.WriteCallSuccess("SKIP", c) | ||||||
|  | 	case failedSt: | ||||||
|  | 		runner.output.WriteCallProblem("FAIL", c) | ||||||
|  | 	case panickedSt: | ||||||
|  | 		runner.output.WriteCallProblem("PANIC", c) | ||||||
|  | 	case fixturePanickedSt: | ||||||
|  | 		// That's a testKd call reporting that its fixture | ||||||
|  | 		// has panicked. The fixture call which caused the | ||||||
|  | 		// panic itself was tracked above. We'll report to | ||||||
|  | 		// aid debugging. | ||||||
|  | 		runner.output.WriteCallProblem("PANIC", c) | ||||||
|  | 	case missedSt: | ||||||
|  | 		runner.output.WriteCallSuccess("MISS", c) | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										458
									
								
								vendor/src/github.com/go-check/check/checkers.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										458
									
								
								vendor/src/github.com/go-check/check/checkers.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,458 @@ | |||||||
|  | package check | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"reflect" | ||||||
|  | 	"regexp" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // CommentInterface and Commentf helper, to attach extra information to checks. | ||||||
|  |  | ||||||
|  | type comment struct { | ||||||
|  | 	format string | ||||||
|  | 	args   []interface{} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Commentf returns an infomational value to use with Assert or Check calls. | ||||||
|  | // If the checker test fails, the provided arguments will be passed to | ||||||
|  | // fmt.Sprintf, and will be presented next to the logged failure. | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //     c.Assert(v, Equals, 42, Commentf("Iteration #%d failed.", i)) | ||||||
|  | // | ||||||
|  | // Note that if the comment is constant, a better option is to | ||||||
|  | // simply use a normal comment right above or next to the line, as | ||||||
|  | // it will also get printed with any errors: | ||||||
|  | // | ||||||
|  | //     c.Assert(l, Equals, 8192) // Ensure buffer size is correct (bug #123) | ||||||
|  | // | ||||||
|  | func Commentf(format string, args ...interface{}) CommentInterface { | ||||||
|  | 	return &comment{format, args} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // CommentInterface must be implemented by types that attach extra | ||||||
|  | // information to failed checks. See the Commentf function for details. | ||||||
|  | type CommentInterface interface { | ||||||
|  | 	CheckCommentString() string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *comment) CheckCommentString() string { | ||||||
|  | 	return fmt.Sprintf(c.format, c.args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // The Checker interface. | ||||||
|  |  | ||||||
|  | // The Checker interface must be provided by checkers used with | ||||||
|  | // the Assert and Check verification methods. | ||||||
|  | type Checker interface { | ||||||
|  | 	Info() *CheckerInfo | ||||||
|  | 	Check(params []interface{}, names []string) (result bool, error string) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // See the Checker interface. | ||||||
|  | type CheckerInfo struct { | ||||||
|  | 	Name   string | ||||||
|  | 	Params []string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (info *CheckerInfo) Info() *CheckerInfo { | ||||||
|  | 	return info | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Not checker logic inverter. | ||||||
|  |  | ||||||
|  | // The Not checker inverts the logic of the provided checker.  The | ||||||
|  | // resulting checker will succeed where the original one failed, and | ||||||
|  | // vice-versa. | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //     c.Assert(a, Not(Equals), b) | ||||||
|  | // | ||||||
|  | func Not(checker Checker) Checker { | ||||||
|  | 	return ¬Checker{checker} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type notChecker struct { | ||||||
|  | 	sub Checker | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker *notChecker) Info() *CheckerInfo { | ||||||
|  | 	info := *checker.sub.Info() | ||||||
|  | 	info.Name = "Not(" + info.Name + ")" | ||||||
|  | 	return &info | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker *notChecker) Check(params []interface{}, names []string) (result bool, error string) { | ||||||
|  | 	result, error = checker.sub.Check(params, names) | ||||||
|  | 	result = !result | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // IsNil checker. | ||||||
|  |  | ||||||
|  | type isNilChecker struct { | ||||||
|  | 	*CheckerInfo | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // The IsNil checker tests whether the obtained value is nil. | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //    c.Assert(err, IsNil) | ||||||
|  | // | ||||||
|  | var IsNil Checker = &isNilChecker{ | ||||||
|  | 	&CheckerInfo{Name: "IsNil", Params: []string{"value"}}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker *isNilChecker) Check(params []interface{}, names []string) (result bool, error string) { | ||||||
|  | 	return isNil(params[0]), "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func isNil(obtained interface{}) (result bool) { | ||||||
|  | 	if obtained == nil { | ||||||
|  | 		result = true | ||||||
|  | 	} else { | ||||||
|  | 		switch v := reflect.ValueOf(obtained); v.Kind() { | ||||||
|  | 		case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: | ||||||
|  | 			return v.IsNil() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // NotNil checker. Alias for Not(IsNil), since it's so common. | ||||||
|  |  | ||||||
|  | type notNilChecker struct { | ||||||
|  | 	*CheckerInfo | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // The NotNil checker verifies that the obtained value is not nil. | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //     c.Assert(iface, NotNil) | ||||||
|  | // | ||||||
|  | // This is an alias for Not(IsNil), made available since it's a | ||||||
|  | // fairly common check. | ||||||
|  | // | ||||||
|  | var NotNil Checker = ¬NilChecker{ | ||||||
|  | 	&CheckerInfo{Name: "NotNil", Params: []string{"value"}}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker *notNilChecker) Check(params []interface{}, names []string) (result bool, error string) { | ||||||
|  | 	return !isNil(params[0]), "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Equals checker. | ||||||
|  |  | ||||||
|  | type equalsChecker struct { | ||||||
|  | 	*CheckerInfo | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // The Equals checker verifies that the obtained value is equal to | ||||||
|  | // the expected value, according to usual Go semantics for ==. | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //     c.Assert(value, Equals, 42) | ||||||
|  | // | ||||||
|  | var Equals Checker = &equalsChecker{ | ||||||
|  | 	&CheckerInfo{Name: "Equals", Params: []string{"obtained", "expected"}}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker *equalsChecker) Check(params []interface{}, names []string) (result bool, error string) { | ||||||
|  | 	defer func() { | ||||||
|  | 		if v := recover(); v != nil { | ||||||
|  | 			result = false | ||||||
|  | 			error = fmt.Sprint(v) | ||||||
|  | 		} | ||||||
|  | 	}() | ||||||
|  | 	return params[0] == params[1], "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // DeepEquals checker. | ||||||
|  |  | ||||||
|  | type deepEqualsChecker struct { | ||||||
|  | 	*CheckerInfo | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // The DeepEquals checker verifies that the obtained value is deep-equal to | ||||||
|  | // the expected value.  The check will work correctly even when facing | ||||||
|  | // slices, interfaces, and values of different types (which always fail | ||||||
|  | // the test). | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //     c.Assert(value, DeepEquals, 42) | ||||||
|  | //     c.Assert(array, DeepEquals, []string{"hi", "there"}) | ||||||
|  | // | ||||||
|  | var DeepEquals Checker = &deepEqualsChecker{ | ||||||
|  | 	&CheckerInfo{Name: "DeepEquals", Params: []string{"obtained", "expected"}}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker *deepEqualsChecker) Check(params []interface{}, names []string) (result bool, error string) { | ||||||
|  | 	return reflect.DeepEqual(params[0], params[1]), "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // HasLen checker. | ||||||
|  |  | ||||||
|  | type hasLenChecker struct { | ||||||
|  | 	*CheckerInfo | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 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 | ||||||
|  | // fails the value itself will be printed, instead of its length, | ||||||
|  | // providing more details for figuring the problem. | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //     c.Assert(list, HasLen, 5) | ||||||
|  | // | ||||||
|  | var HasLen Checker = &hasLenChecker{ | ||||||
|  | 	&CheckerInfo{Name: "HasLen", Params: []string{"obtained", "n"}}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker *hasLenChecker) Check(params []interface{}, names []string) (result bool, error string) { | ||||||
|  | 	n, ok := params[1].(int) | ||||||
|  | 	if !ok { | ||||||
|  | 		return false, "n must be an int" | ||||||
|  | 	} | ||||||
|  | 	value := reflect.ValueOf(params[0]) | ||||||
|  | 	switch value.Kind() { | ||||||
|  | 	case reflect.Map, reflect.Array, reflect.Slice, reflect.Chan, reflect.String: | ||||||
|  | 	default: | ||||||
|  | 		return false, "obtained value type has no length" | ||||||
|  | 	} | ||||||
|  | 	return value.Len() == n, "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // ErrorMatches checker. | ||||||
|  |  | ||||||
|  | type errorMatchesChecker struct { | ||||||
|  | 	*CheckerInfo | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // The ErrorMatches checker verifies that the error value | ||||||
|  | // is non nil and matches the regular expression provided. | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //     c.Assert(err, ErrorMatches, "perm.*denied") | ||||||
|  | // | ||||||
|  | var ErrorMatches Checker = errorMatchesChecker{ | ||||||
|  | 	&CheckerInfo{Name: "ErrorMatches", Params: []string{"value", "regex"}}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker errorMatchesChecker) Check(params []interface{}, names []string) (result bool, errStr string) { | ||||||
|  | 	if params[0] == nil { | ||||||
|  | 		return false, "Error value is nil" | ||||||
|  | 	} | ||||||
|  | 	err, ok := params[0].(error) | ||||||
|  | 	if !ok { | ||||||
|  | 		return false, "Value is not an error" | ||||||
|  | 	} | ||||||
|  | 	params[0] = err.Error() | ||||||
|  | 	names[0] = "error" | ||||||
|  | 	return matches(params[0], params[1]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Matches checker. | ||||||
|  |  | ||||||
|  | type matchesChecker struct { | ||||||
|  | 	*CheckerInfo | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // The Matches checker verifies that the string provided as the obtained | ||||||
|  | // value (or the string resulting from obtained.String()) matches the | ||||||
|  | // regular expression provided. | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //     c.Assert(err, Matches, "perm.*denied") | ||||||
|  | // | ||||||
|  | var Matches Checker = &matchesChecker{ | ||||||
|  | 	&CheckerInfo{Name: "Matches", Params: []string{"value", "regex"}}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker *matchesChecker) Check(params []interface{}, names []string) (result bool, error string) { | ||||||
|  | 	return matches(params[0], params[1]) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func matches(value, regex interface{}) (result bool, error string) { | ||||||
|  | 	reStr, ok := regex.(string) | ||||||
|  | 	if !ok { | ||||||
|  | 		return false, "Regex must be a string" | ||||||
|  | 	} | ||||||
|  | 	valueStr, valueIsStr := value.(string) | ||||||
|  | 	if !valueIsStr { | ||||||
|  | 		if valueWithStr, valueHasStr := value.(fmt.Stringer); valueHasStr { | ||||||
|  | 			valueStr, valueIsStr = valueWithStr.String(), true | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if valueIsStr { | ||||||
|  | 		matches, err := regexp.MatchString("^"+reStr+"$", valueStr) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return false, "Can't compile regex: " + err.Error() | ||||||
|  | 		} | ||||||
|  | 		return matches, "" | ||||||
|  | 	} | ||||||
|  | 	return false, "Obtained value is not a string and has no .String()" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Panics checker. | ||||||
|  |  | ||||||
|  | type panicsChecker struct { | ||||||
|  | 	*CheckerInfo | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // The Panics checker verifies that calling the provided zero-argument | ||||||
|  | // function will cause a panic which is deep-equal to the provided value. | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //     c.Assert(func() { f(1, 2) }, Panics, &SomeErrorType{"BOOM"}). | ||||||
|  | // | ||||||
|  | // | ||||||
|  | var Panics Checker = &panicsChecker{ | ||||||
|  | 	&CheckerInfo{Name: "Panics", Params: []string{"function", "expected"}}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker *panicsChecker) Check(params []interface{}, names []string) (result bool, error string) { | ||||||
|  | 	f := reflect.ValueOf(params[0]) | ||||||
|  | 	if f.Kind() != reflect.Func || f.Type().NumIn() != 0 { | ||||||
|  | 		return false, "Function must take zero arguments" | ||||||
|  | 	} | ||||||
|  | 	defer func() { | ||||||
|  | 		// If the function has not panicked, then don't do the check. | ||||||
|  | 		if error != "" { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		params[0] = recover() | ||||||
|  | 		names[0] = "panic" | ||||||
|  | 		result = reflect.DeepEqual(params[0], params[1]) | ||||||
|  | 	}() | ||||||
|  | 	f.Call(nil) | ||||||
|  | 	return false, "Function has not panicked" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type panicMatchesChecker struct { | ||||||
|  | 	*CheckerInfo | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // The PanicMatches checker verifies that calling the provided zero-argument | ||||||
|  | // function will cause a panic with an error value matching | ||||||
|  | // the regular expression provided. | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //     c.Assert(func() { f(1, 2) }, PanicMatches, `open.*: no such file or directory`). | ||||||
|  | // | ||||||
|  | // | ||||||
|  | var PanicMatches Checker = &panicMatchesChecker{ | ||||||
|  | 	&CheckerInfo{Name: "PanicMatches", Params: []string{"function", "expected"}}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker *panicMatchesChecker) Check(params []interface{}, names []string) (result bool, errmsg string) { | ||||||
|  | 	f := reflect.ValueOf(params[0]) | ||||||
|  | 	if f.Kind() != reflect.Func || f.Type().NumIn() != 0 { | ||||||
|  | 		return false, "Function must take zero arguments" | ||||||
|  | 	} | ||||||
|  | 	defer func() { | ||||||
|  | 		// If the function has not panicked, then don't do the check. | ||||||
|  | 		if errmsg != "" { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		obtained := recover() | ||||||
|  | 		names[0] = "panic" | ||||||
|  | 		if e, ok := obtained.(error); ok { | ||||||
|  | 			params[0] = e.Error() | ||||||
|  | 		} else if _, ok := obtained.(string); ok { | ||||||
|  | 			params[0] = obtained | ||||||
|  | 		} else { | ||||||
|  | 			errmsg = "Panic value is not a string or an error" | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		result, errmsg = matches(params[0], params[1]) | ||||||
|  | 	}() | ||||||
|  | 	f.Call(nil) | ||||||
|  | 	return false, "Function has not panicked" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // FitsTypeOf checker. | ||||||
|  |  | ||||||
|  | type fitsTypeChecker struct { | ||||||
|  | 	*CheckerInfo | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // The FitsTypeOf checker verifies that the obtained value is | ||||||
|  | // assignable to a variable with the same type as the provided | ||||||
|  | // sample value. | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //     c.Assert(value, FitsTypeOf, int64(0)) | ||||||
|  | //     c.Assert(value, FitsTypeOf, os.Error(nil)) | ||||||
|  | // | ||||||
|  | var FitsTypeOf Checker = &fitsTypeChecker{ | ||||||
|  | 	&CheckerInfo{Name: "FitsTypeOf", Params: []string{"obtained", "sample"}}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker *fitsTypeChecker) Check(params []interface{}, names []string) (result bool, error string) { | ||||||
|  | 	obtained := reflect.ValueOf(params[0]) | ||||||
|  | 	sample := reflect.ValueOf(params[1]) | ||||||
|  | 	if !obtained.IsValid() { | ||||||
|  | 		return false, "" | ||||||
|  | 	} | ||||||
|  | 	if !sample.IsValid() { | ||||||
|  | 		return false, "Invalid sample value" | ||||||
|  | 	} | ||||||
|  | 	return obtained.Type().AssignableTo(sample.Type()), "" | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Implements checker. | ||||||
|  |  | ||||||
|  | type implementsChecker struct { | ||||||
|  | 	*CheckerInfo | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // The Implements checker verifies that the obtained value | ||||||
|  | // implements the interface specified via a pointer to an interface | ||||||
|  | // variable. | ||||||
|  | // | ||||||
|  | // For example: | ||||||
|  | // | ||||||
|  | //     var e os.Error | ||||||
|  | //     c.Assert(err, Implements, &e) | ||||||
|  | // | ||||||
|  | var Implements Checker = &implementsChecker{ | ||||||
|  | 	&CheckerInfo{Name: "Implements", Params: []string{"obtained", "ifaceptr"}}, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (checker *implementsChecker) Check(params []interface{}, names []string) (result bool, error string) { | ||||||
|  | 	obtained := reflect.ValueOf(params[0]) | ||||||
|  | 	ifaceptr := reflect.ValueOf(params[1]) | ||||||
|  | 	if !obtained.IsValid() { | ||||||
|  | 		return false, "" | ||||||
|  | 	} | ||||||
|  | 	if !ifaceptr.IsValid() || ifaceptr.Kind() != reflect.Ptr || ifaceptr.Elem().Kind() != reflect.Interface { | ||||||
|  | 		return false, "ifaceptr should be a pointer to an interface variable" | ||||||
|  | 	} | ||||||
|  | 	return obtained.Type().Implements(ifaceptr.Elem().Type()), "" | ||||||
|  | } | ||||||
							
								
								
									
										231
									
								
								vendor/src/github.com/go-check/check/helpers.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								vendor/src/github.com/go-check/check/helpers.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,231 @@ | |||||||
|  | package check | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // TestName returns the current test name in the form "SuiteName.TestName" | ||||||
|  | func (c *C) TestName() string { | ||||||
|  | 	return c.testName | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Basic succeeding/failing logic. | ||||||
|  |  | ||||||
|  | // Failed returns whether the currently running test has already failed. | ||||||
|  | func (c *C) Failed() bool { | ||||||
|  | 	return c.status() == failedSt | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Fail marks the currently running test as failed. | ||||||
|  | // | ||||||
|  | // Something ought to have been previously logged so the developer can tell | ||||||
|  | // what went wrong. The higher level helper functions will fail the test | ||||||
|  | // and do the logging properly. | ||||||
|  | func (c *C) Fail() { | ||||||
|  | 	c.setStatus(failedSt) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // FailNow marks the currently running test as failed and stops running it. | ||||||
|  | // Something ought to have been previously logged so the developer can tell | ||||||
|  | // what went wrong. The higher level helper functions will fail the test | ||||||
|  | // and do the logging properly. | ||||||
|  | func (c *C) FailNow() { | ||||||
|  | 	c.Fail() | ||||||
|  | 	c.stopNow() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Succeed marks the currently running test as succeeded, undoing any | ||||||
|  | // previous failures. | ||||||
|  | func (c *C) Succeed() { | ||||||
|  | 	c.setStatus(succeededSt) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // SucceedNow marks the currently running test as succeeded, undoing any | ||||||
|  | // previous failures, and stops running the test. | ||||||
|  | func (c *C) SucceedNow() { | ||||||
|  | 	c.Succeed() | ||||||
|  | 	c.stopNow() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ExpectFailure informs that the running test is knowingly broken for | ||||||
|  | // the provided reason. If the test does not fail, an error will be reported | ||||||
|  | // to raise attention to this fact. This method is useful to temporarily | ||||||
|  | // disable tests which cover well known problems until a better time to | ||||||
|  | // fix the problem is found, without forgetting about the fact that a | ||||||
|  | // failure still exists. | ||||||
|  | func (c *C) ExpectFailure(reason string) { | ||||||
|  | 	if reason == "" { | ||||||
|  | 		panic("Missing reason why the test is expected to fail") | ||||||
|  | 	} | ||||||
|  | 	c.mustFail = true | ||||||
|  | 	c.reason = reason | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Skip skips the running test for the provided reason. If run from within | ||||||
|  | // SetUpTest, the individual test being set up will be skipped, and if run | ||||||
|  | // from within SetUpSuite, the whole suite is skipped. | ||||||
|  | func (c *C) Skip(reason string) { | ||||||
|  | 	if reason == "" { | ||||||
|  | 		panic("Missing reason why the test is being skipped") | ||||||
|  | 	} | ||||||
|  | 	c.reason = reason | ||||||
|  | 	c.setStatus(skippedSt) | ||||||
|  | 	c.stopNow() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Basic logging. | ||||||
|  |  | ||||||
|  | // GetTestLog returns the current test error output. | ||||||
|  | func (c *C) GetTestLog() string { | ||||||
|  | 	return c.logb.String() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Log logs some information into the test error output. | ||||||
|  | // The provided arguments are assembled together into a string with fmt.Sprint. | ||||||
|  | func (c *C) Log(args ...interface{}) { | ||||||
|  | 	c.log(args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Log logs some information into the test error output. | ||||||
|  | // The provided arguments are assembled together into a string with fmt.Sprintf. | ||||||
|  | func (c *C) Logf(format string, args ...interface{}) { | ||||||
|  | 	c.logf(format, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Output enables *C to be used as a logger in functions that require only | ||||||
|  | // the minimum interface of *log.Logger. | ||||||
|  | func (c *C) Output(calldepth int, s string) error { | ||||||
|  | 	d := time.Now().Sub(c.startTime) | ||||||
|  | 	msec := d / time.Millisecond | ||||||
|  | 	sec := d / time.Second | ||||||
|  | 	min := d / time.Minute | ||||||
|  |  | ||||||
|  | 	c.Logf("[LOG] %d:%02d.%03d %s", min, sec%60, msec%1000, s) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Error logs an error into the test error output and marks the test as failed. | ||||||
|  | // The provided arguments are assembled together into a string with fmt.Sprint. | ||||||
|  | func (c *C) Error(args ...interface{}) { | ||||||
|  | 	c.logCaller(1) | ||||||
|  | 	c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...))) | ||||||
|  | 	c.logNewLine() | ||||||
|  | 	c.Fail() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Errorf logs an error into the test error output and marks the test as failed. | ||||||
|  | // The provided arguments are assembled together into a string with fmt.Sprintf. | ||||||
|  | func (c *C) Errorf(format string, args ...interface{}) { | ||||||
|  | 	c.logCaller(1) | ||||||
|  | 	c.logString(fmt.Sprintf("Error: "+format, args...)) | ||||||
|  | 	c.logNewLine() | ||||||
|  | 	c.Fail() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Fatal logs an error into the test error output, marks the test as failed, and | ||||||
|  | // stops the test execution. The provided arguments are assembled together into | ||||||
|  | // a string with fmt.Sprint. | ||||||
|  | func (c *C) Fatal(args ...interface{}) { | ||||||
|  | 	c.logCaller(1) | ||||||
|  | 	c.logString(fmt.Sprint("Error: ", fmt.Sprint(args...))) | ||||||
|  | 	c.logNewLine() | ||||||
|  | 	c.FailNow() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Fatlaf logs an error into the test error output, marks the test as failed, and | ||||||
|  | // stops the test execution. The provided arguments are assembled together into | ||||||
|  | // a string with fmt.Sprintf. | ||||||
|  | func (c *C) Fatalf(format string, args ...interface{}) { | ||||||
|  | 	c.logCaller(1) | ||||||
|  | 	c.logString(fmt.Sprint("Error: ", fmt.Sprintf(format, args...))) | ||||||
|  | 	c.logNewLine() | ||||||
|  | 	c.FailNow() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Generic checks and assertions based on checkers. | ||||||
|  |  | ||||||
|  | // Check verifies if the first value matches the expected value according | ||||||
|  | // to the provided checker. If they do not match, an error is logged, the | ||||||
|  | // test is marked as failed, and the test execution continues. | ||||||
|  | // | ||||||
|  | // Some checkers may not need the expected argument (e.g. IsNil). | ||||||
|  | // | ||||||
|  | // Extra arguments provided to the function are logged next to the reported | ||||||
|  | // problem when the matching fails. | ||||||
|  | func (c *C) Check(obtained interface{}, checker Checker, args ...interface{}) bool { | ||||||
|  | 	return c.internalCheck("Check", obtained, checker, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Assert ensures that the first value matches the expected value according | ||||||
|  | // to the provided checker. If they do not match, an error is logged, the | ||||||
|  | // test is marked as failed, and the test execution stops. | ||||||
|  | // | ||||||
|  | // Some checkers may not need the expected argument (e.g. IsNil). | ||||||
|  | // | ||||||
|  | // Extra arguments provided to the function are logged next to the reported | ||||||
|  | // problem when the matching fails. | ||||||
|  | func (c *C) Assert(obtained interface{}, checker Checker, args ...interface{}) { | ||||||
|  | 	if !c.internalCheck("Assert", obtained, checker, args...) { | ||||||
|  | 		c.stopNow() | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *C) internalCheck(funcName string, obtained interface{}, checker Checker, args ...interface{}) bool { | ||||||
|  | 	if checker == nil { | ||||||
|  | 		c.logCaller(2) | ||||||
|  | 		c.logString(fmt.Sprintf("%s(obtained, nil!?, ...):", funcName)) | ||||||
|  | 		c.logString("Oops.. you've provided a nil checker!") | ||||||
|  | 		c.logNewLine() | ||||||
|  | 		c.Fail() | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// If the last argument is a bug info, extract it out. | ||||||
|  | 	var comment CommentInterface | ||||||
|  | 	if len(args) > 0 { | ||||||
|  | 		if c, ok := args[len(args)-1].(CommentInterface); ok { | ||||||
|  | 			comment = c | ||||||
|  | 			args = args[:len(args)-1] | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	params := append([]interface{}{obtained}, args...) | ||||||
|  | 	info := checker.Info() | ||||||
|  |  | ||||||
|  | 	if len(params) != len(info.Params) { | ||||||
|  | 		names := append([]string{info.Params[0], info.Name}, info.Params[1:]...) | ||||||
|  | 		c.logCaller(2) | ||||||
|  | 		c.logString(fmt.Sprintf("%s(%s):", funcName, strings.Join(names, ", "))) | ||||||
|  | 		c.logString(fmt.Sprintf("Wrong number of parameters for %s: want %d, got %d", info.Name, len(names), len(params)+1)) | ||||||
|  | 		c.logNewLine() | ||||||
|  | 		c.Fail() | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Copy since it may be mutated by Check. | ||||||
|  | 	names := append([]string{}, info.Params...) | ||||||
|  |  | ||||||
|  | 	// Do the actual check. | ||||||
|  | 	result, error := checker.Check(params, names) | ||||||
|  | 	if !result || error != "" { | ||||||
|  | 		c.logCaller(2) | ||||||
|  | 		for i := 0; i != len(params); i++ { | ||||||
|  | 			c.logValue(names[i], params[i]) | ||||||
|  | 		} | ||||||
|  | 		if comment != nil { | ||||||
|  | 			c.logString(comment.CheckCommentString()) | ||||||
|  | 		} | ||||||
|  | 		if error != "" { | ||||||
|  | 			c.logString(error) | ||||||
|  | 		} | ||||||
|  | 		c.logNewLine() | ||||||
|  | 		c.Fail() | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	return true | ||||||
|  | } | ||||||
							
								
								
									
										168
									
								
								vendor/src/github.com/go-check/check/printer.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								vendor/src/github.com/go-check/check/printer.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,168 @@ | |||||||
|  | package check | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bytes" | ||||||
|  | 	"go/ast" | ||||||
|  | 	"go/parser" | ||||||
|  | 	"go/printer" | ||||||
|  | 	"go/token" | ||||||
|  | 	"os" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func indent(s, with string) (r string) { | ||||||
|  | 	eol := true | ||||||
|  | 	for i := 0; i != len(s); i++ { | ||||||
|  | 		c := s[i] | ||||||
|  | 		switch { | ||||||
|  | 		case eol && c == '\n' || c == '\r': | ||||||
|  | 		case c == '\n' || c == '\r': | ||||||
|  | 			eol = true | ||||||
|  | 		case eol: | ||||||
|  | 			eol = false | ||||||
|  | 			s = s[:i] + with + s[i:] | ||||||
|  | 			i += len(with) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return s | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func printLine(filename string, line int) (string, error) { | ||||||
|  | 	fset := token.NewFileSet() | ||||||
|  | 	file, err := os.Open(filename) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	fnode, err := parser.ParseFile(fset, filename, file, parser.ParseComments) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", err | ||||||
|  | 	} | ||||||
|  | 	config := &printer.Config{Mode: printer.UseSpaces, Tabwidth: 4} | ||||||
|  | 	lp := &linePrinter{fset: fset, fnode: fnode, line: line, config: config} | ||||||
|  | 	ast.Walk(lp, fnode) | ||||||
|  | 	result := lp.output.Bytes() | ||||||
|  | 	// Comments leave \n at the end. | ||||||
|  | 	n := len(result) | ||||||
|  | 	for n > 0 && result[n-1] == '\n' { | ||||||
|  | 		n-- | ||||||
|  | 	} | ||||||
|  | 	return string(result[:n]), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type linePrinter struct { | ||||||
|  | 	config *printer.Config | ||||||
|  | 	fset   *token.FileSet | ||||||
|  | 	fnode  *ast.File | ||||||
|  | 	line   int | ||||||
|  | 	output bytes.Buffer | ||||||
|  | 	stmt   ast.Stmt | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (lp *linePrinter) emit() bool { | ||||||
|  | 	if lp.stmt != nil { | ||||||
|  | 		lp.trim(lp.stmt) | ||||||
|  | 		lp.printWithComments(lp.stmt) | ||||||
|  | 		lp.stmt = nil | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 	return false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (lp *linePrinter) printWithComments(n ast.Node) { | ||||||
|  | 	nfirst := lp.fset.Position(n.Pos()).Line | ||||||
|  | 	nlast := lp.fset.Position(n.End()).Line | ||||||
|  | 	for _, g := range lp.fnode.Comments { | ||||||
|  | 		cfirst := lp.fset.Position(g.Pos()).Line | ||||||
|  | 		clast := lp.fset.Position(g.End()).Line | ||||||
|  | 		if clast == nfirst-1 && lp.fset.Position(n.Pos()).Column == lp.fset.Position(g.Pos()).Column { | ||||||
|  | 			for _, c := range g.List { | ||||||
|  | 				lp.output.WriteString(c.Text) | ||||||
|  | 				lp.output.WriteByte('\n') | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if cfirst >= nfirst && cfirst <= nlast && n.End() <= g.List[0].Slash { | ||||||
|  | 			// The printer will not include the comment if it starts past | ||||||
|  | 			// the node itself. Trick it into printing by overlapping the | ||||||
|  | 			// slash with the end of the statement. | ||||||
|  | 			g.List[0].Slash = n.End() - 1 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	node := &printer.CommentedNode{n, lp.fnode.Comments} | ||||||
|  | 	lp.config.Fprint(&lp.output, lp.fset, node) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (lp *linePrinter) Visit(n ast.Node) (w ast.Visitor) { | ||||||
|  | 	if n == nil { | ||||||
|  | 		if lp.output.Len() == 0 { | ||||||
|  | 			lp.emit() | ||||||
|  | 		} | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  | 	first := lp.fset.Position(n.Pos()).Line | ||||||
|  | 	last := lp.fset.Position(n.End()).Line | ||||||
|  | 	if first <= lp.line && last >= lp.line { | ||||||
|  | 		// Print the innermost statement containing the line. | ||||||
|  | 		if stmt, ok := n.(ast.Stmt); ok { | ||||||
|  | 			if _, ok := n.(*ast.BlockStmt); !ok { | ||||||
|  | 				lp.stmt = stmt | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if first == lp.line && lp.emit() { | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 		return lp | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (lp *linePrinter) trim(n ast.Node) bool { | ||||||
|  | 	stmt, ok := n.(ast.Stmt) | ||||||
|  | 	if !ok { | ||||||
|  | 		return true | ||||||
|  | 	} | ||||||
|  | 	line := lp.fset.Position(n.Pos()).Line | ||||||
|  | 	if line != lp.line { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  | 	switch stmt := stmt.(type) { | ||||||
|  | 	case *ast.IfStmt: | ||||||
|  | 		stmt.Body = lp.trimBlock(stmt.Body) | ||||||
|  | 	case *ast.SwitchStmt: | ||||||
|  | 		stmt.Body = lp.trimBlock(stmt.Body) | ||||||
|  | 	case *ast.TypeSwitchStmt: | ||||||
|  | 		stmt.Body = lp.trimBlock(stmt.Body) | ||||||
|  | 	case *ast.CaseClause: | ||||||
|  | 		stmt.Body = lp.trimList(stmt.Body) | ||||||
|  | 	case *ast.CommClause: | ||||||
|  | 		stmt.Body = lp.trimList(stmt.Body) | ||||||
|  | 	case *ast.BlockStmt: | ||||||
|  | 		stmt.List = lp.trimList(stmt.List) | ||||||
|  | 	} | ||||||
|  | 	return true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (lp *linePrinter) trimBlock(stmt *ast.BlockStmt) *ast.BlockStmt { | ||||||
|  | 	if !lp.trim(stmt) { | ||||||
|  | 		return lp.emptyBlock(stmt) | ||||||
|  | 	} | ||||||
|  | 	stmt.Rbrace = stmt.Lbrace | ||||||
|  | 	return stmt | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (lp *linePrinter) trimList(stmts []ast.Stmt) []ast.Stmt { | ||||||
|  | 	for i := 0; i != len(stmts); i++ { | ||||||
|  | 		if !lp.trim(stmts[i]) { | ||||||
|  | 			stmts[i] = lp.emptyStmt(stmts[i]) | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return stmts | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (lp *linePrinter) emptyStmt(n ast.Node) *ast.ExprStmt { | ||||||
|  | 	return &ast.ExprStmt{&ast.Ellipsis{n.Pos(), nil}} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (lp *linePrinter) emptyBlock(n ast.Node) *ast.BlockStmt { | ||||||
|  | 	p := n.Pos() | ||||||
|  | 	return &ast.BlockStmt{p, []ast.Stmt{lp.emptyStmt(n)}, p} | ||||||
|  | } | ||||||
							
								
								
									
										88
									
								
								vendor/src/github.com/go-check/check/reporter.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								vendor/src/github.com/go-check/check/reporter.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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) | ||||||
|  | } | ||||||
							
								
								
									
										183
									
								
								vendor/src/github.com/go-check/check/run.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										183
									
								
								vendor/src/github.com/go-check/check/run.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,183 @@ | |||||||
|  | package check | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"bufio" | ||||||
|  | 	"flag" | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"testing" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Test suite registry. | ||||||
|  |  | ||||||
|  | var allSuites []interface{} | ||||||
|  |  | ||||||
|  | // Suite registers the given value as a test suite to be run. Any methods | ||||||
|  | // starting with the Test prefix in the given value will be considered as | ||||||
|  | // a test method. | ||||||
|  | func Suite(suite interface{}) interface{} { | ||||||
|  | 	allSuites = append(allSuites, suite) | ||||||
|  | 	return suite | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Public running interface. | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	oldFilterFlag  = flag.String("gocheck.f", "", "Regular expression selecting which tests and/or suites to run") | ||||||
|  | 	oldVerboseFlag = flag.Bool("gocheck.v", false, "Verbose mode") | ||||||
|  | 	oldStreamFlag  = flag.Bool("gocheck.vv", false, "Super verbose mode (disables output caching)") | ||||||
|  | 	oldBenchFlag   = flag.Bool("gocheck.b", false, "Run benchmarks") | ||||||
|  | 	oldBenchTime   = flag.Duration("gocheck.btime", 1*time.Second, "approximate run time for each benchmark") | ||||||
|  | 	oldListFlag    = flag.Bool("gocheck.list", false, "List the names of all tests that will be run") | ||||||
|  | 	oldWorkFlag    = flag.Bool("gocheck.work", false, "Display and do not remove the test working directory") | ||||||
|  |  | ||||||
|  | 	newFilterFlag  = flag.String("check.f", "", "Regular expression selecting which tests and/or suites to run") | ||||||
|  | 	newVerboseFlag = flag.Bool("check.v", false, "Verbose mode") | ||||||
|  | 	newStreamFlag  = flag.Bool("check.vv", false, "Super verbose mode (disables output caching)") | ||||||
|  | 	newBenchFlag   = flag.Bool("check.b", false, "Run benchmarks") | ||||||
|  | 	newBenchTime   = flag.Duration("check.btime", 1*time.Second, "approximate run time for each benchmark") | ||||||
|  | 	newBenchMem    = flag.Bool("check.bmem", false, "Report memory benchmarks") | ||||||
|  | 	newListFlag    = flag.Bool("check.list", false, "List the names of all tests that will be run") | ||||||
|  | 	newWorkFlag    = flag.Bool("check.work", false, "Display and do not remove the test working directory") | ||||||
|  | 	checkTimeout   = flag.String("check.timeout", "", "Panic if test runs longer than specified duration") | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // TestingT runs all test suites registered with the Suite function, | ||||||
|  | // printing results to stdout, and reporting any failures back to | ||||||
|  | // the "testing" package. | ||||||
|  | func TestingT(testingT *testing.T) { | ||||||
|  | 	benchTime := *newBenchTime | ||||||
|  | 	if benchTime == 1*time.Second { | ||||||
|  | 		benchTime = *oldBenchTime | ||||||
|  | 	} | ||||||
|  | 	conf := &RunConf{ | ||||||
|  | 		Filter:        *oldFilterFlag + *newFilterFlag, | ||||||
|  | 		Verbose:       *oldVerboseFlag || *newVerboseFlag, | ||||||
|  | 		Stream:        *oldStreamFlag || *newStreamFlag, | ||||||
|  | 		Benchmark:     *oldBenchFlag || *newBenchFlag, | ||||||
|  | 		BenchmarkTime: benchTime, | ||||||
|  | 		BenchmarkMem:  *newBenchMem, | ||||||
|  | 		KeepWorkDir:   *oldWorkFlag || *newWorkFlag, | ||||||
|  | 	} | ||||||
|  | 	if *checkTimeout != "" { | ||||||
|  | 		timeout, err := time.ParseDuration(*checkTimeout) | ||||||
|  | 		if err != nil { | ||||||
|  | 			testingT.Fatalf("error parsing specified timeout flag: %v", err) | ||||||
|  | 		} | ||||||
|  | 		conf.CheckTimeout = timeout | ||||||
|  | 	} | ||||||
|  | 	if *oldListFlag || *newListFlag { | ||||||
|  | 		w := bufio.NewWriter(os.Stdout) | ||||||
|  | 		for _, name := range ListAll(conf) { | ||||||
|  | 			fmt.Fprintln(w, name) | ||||||
|  | 		} | ||||||
|  | 		w.Flush() | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	result := RunAll(conf) | ||||||
|  | 	println(result.String()) | ||||||
|  | 	if !result.Passed() { | ||||||
|  | 		testingT.Fail() | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // RunAll runs all test suites registered with the Suite function, using the | ||||||
|  | // provided run configuration. | ||||||
|  | func RunAll(runConf *RunConf) *Result { | ||||||
|  | 	result := Result{} | ||||||
|  | 	for _, suite := range allSuites { | ||||||
|  | 		result.Add(Run(suite, runConf)) | ||||||
|  | 	} | ||||||
|  | 	return &result | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Run runs the provided test suite using the provided run configuration. | ||||||
|  | func Run(suite interface{}, runConf *RunConf) *Result { | ||||||
|  | 	runner := newSuiteRunner(suite, runConf) | ||||||
|  | 	return runner.run() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ListAll returns the names of all the test functions registered with the | ||||||
|  | // Suite function that will be run with the provided run configuration. | ||||||
|  | func ListAll(runConf *RunConf) []string { | ||||||
|  | 	var names []string | ||||||
|  | 	for _, suite := range allSuites { | ||||||
|  | 		names = append(names, List(suite, runConf)...) | ||||||
|  | 	} | ||||||
|  | 	return names | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // List returns the names of the test functions in the given | ||||||
|  | // suite that will be run with the provided run configuration. | ||||||
|  | func List(suite interface{}, runConf *RunConf) []string { | ||||||
|  | 	var names []string | ||||||
|  | 	runner := newSuiteRunner(suite, runConf) | ||||||
|  | 	for _, t := range runner.tests { | ||||||
|  | 		names = append(names, t.String()) | ||||||
|  | 	} | ||||||
|  | 	return names | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ----------------------------------------------------------------------- | ||||||
|  | // Result methods. | ||||||
|  |  | ||||||
|  | func (r *Result) Add(other *Result) { | ||||||
|  | 	r.Succeeded += other.Succeeded | ||||||
|  | 	r.Skipped += other.Skipped | ||||||
|  | 	r.Failed += other.Failed | ||||||
|  | 	r.Panicked += other.Panicked | ||||||
|  | 	r.FixturePanicked += other.FixturePanicked | ||||||
|  | 	r.ExpectedFailures += other.ExpectedFailures | ||||||
|  | 	r.Missed += other.Missed | ||||||
|  | 	if r.WorkDir != "" && other.WorkDir != "" { | ||||||
|  | 		r.WorkDir += ":" + other.WorkDir | ||||||
|  | 	} else if other.WorkDir != "" { | ||||||
|  | 		r.WorkDir = other.WorkDir | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r *Result) Passed() bool { | ||||||
|  | 	return (r.Failed == 0 && r.Panicked == 0 && | ||||||
|  | 		r.FixturePanicked == 0 && r.Missed == 0 && | ||||||
|  | 		r.RunError == nil) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r *Result) String() string { | ||||||
|  | 	if r.RunError != nil { | ||||||
|  | 		return "ERROR: " + r.RunError.Error() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var value string | ||||||
|  | 	if r.Failed == 0 && r.Panicked == 0 && r.FixturePanicked == 0 && | ||||||
|  | 		r.Missed == 0 { | ||||||
|  | 		value = "OK: " | ||||||
|  | 	} else { | ||||||
|  | 		value = "OOPS: " | ||||||
|  | 	} | ||||||
|  | 	value += fmt.Sprintf("%d passed", r.Succeeded) | ||||||
|  | 	if r.Skipped != 0 { | ||||||
|  | 		value += fmt.Sprintf(", %d skipped", r.Skipped) | ||||||
|  | 	} | ||||||
|  | 	if r.ExpectedFailures != 0 { | ||||||
|  | 		value += fmt.Sprintf(", %d expected failures", r.ExpectedFailures) | ||||||
|  | 	} | ||||||
|  | 	if r.Failed != 0 { | ||||||
|  | 		value += fmt.Sprintf(", %d FAILED", r.Failed) | ||||||
|  | 	} | ||||||
|  | 	if r.Panicked != 0 { | ||||||
|  | 		value += fmt.Sprintf(", %d PANICKED", r.Panicked) | ||||||
|  | 	} | ||||||
|  | 	if r.FixturePanicked != 0 { | ||||||
|  | 		value += fmt.Sprintf(", %d FIXTURE-PANICKED", r.FixturePanicked) | ||||||
|  | 	} | ||||||
|  | 	if r.Missed != 0 { | ||||||
|  | 		value += fmt.Sprintf(", %d MISSED", r.Missed) | ||||||
|  | 	} | ||||||
|  | 	if r.WorkDir != "" { | ||||||
|  | 		value += "\nWORK=" + r.WorkDir | ||||||
|  | 	} | ||||||
|  | 	return value | ||||||
|  | } | ||||||
							
								
								
									
										2
									
								
								vendor/src/github.com/vdemeester/shakers/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								vendor/src/github.com/vdemeester/shakers/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | |||||||
|  | vendor | ||||||
|  | *.test | ||||||
							
								
								
									
										16
									
								
								vendor/src/github.com/vdemeester/shakers/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/src/github.com/vdemeester/shakers/Dockerfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | 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 | ||||||
|  | RUN go get github.com/Masterminds/glide | ||||||
|  |  | ||||||
|  | WORKDIR /go/src/github.com/vdemeester/shakers | ||||||
|  |  | ||||||
|  | # enable GO15VENDOREXPERIMENT | ||||||
|  | ENV GO15VENDOREXPERIMENT 1 | ||||||
|  |  | ||||||
|  | COPY glide.yaml glide.yaml | ||||||
|  | RUN glide up | ||||||
|  |  | ||||||
|  | COPY . /go/src/github.com/vdemeester/shakers | ||||||
							
								
								
									
										191
									
								
								vendor/src/github.com/vdemeester/shakers/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/src/github.com/vdemeester/shakers/LICENSE
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | |||||||
|  |  | ||||||
|  |                                  Apache License | ||||||
|  |                            Version 2.0, January 2004 | ||||||
|  |                         https://www.apache.org/licenses/ | ||||||
|  |  | ||||||
|  |    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | ||||||
|  |  | ||||||
|  |    1. Definitions. | ||||||
|  |  | ||||||
|  |       "License" shall mean the terms and conditions for use, reproduction, | ||||||
|  |       and distribution as defined by Sections 1 through 9 of this document. | ||||||
|  |  | ||||||
|  |       "Licensor" shall mean the copyright owner or entity authorized by | ||||||
|  |       the copyright owner that is granting the License. | ||||||
|  |  | ||||||
|  |       "Legal Entity" shall mean the union of the acting entity and all | ||||||
|  |       other entities that control, are controlled by, or are under common | ||||||
|  |       control with that entity. For the purposes of this definition, | ||||||
|  |       "control" means (i) the power, direct or indirect, to cause the | ||||||
|  |       direction or management of such entity, whether by contract or | ||||||
|  |       otherwise, or (ii) ownership of fifty percent (50%) or more of the | ||||||
|  |       outstanding shares, or (iii) beneficial ownership of such entity. | ||||||
|  |  | ||||||
|  |       "You" (or "Your") shall mean an individual or Legal Entity | ||||||
|  |       exercising permissions granted by this License. | ||||||
|  |  | ||||||
|  |       "Source" form shall mean the preferred form for making modifications, | ||||||
|  |       including but not limited to software source code, documentation | ||||||
|  |       source, and configuration files. | ||||||
|  |  | ||||||
|  |       "Object" form shall mean any form resulting from mechanical | ||||||
|  |       transformation or translation of a Source form, including but | ||||||
|  |       not limited to compiled object code, generated documentation, | ||||||
|  |       and conversions to other media types. | ||||||
|  |  | ||||||
|  |       "Work" shall mean the work of authorship, whether in Source or | ||||||
|  |       Object form, made available under the License, as indicated by a | ||||||
|  |       copyright notice that is included in or attached to the work | ||||||
|  |       (an example is provided in the Appendix below). | ||||||
|  |  | ||||||
|  |       "Derivative Works" shall mean any work, whether in Source or Object | ||||||
|  |       form, that is based on (or derived from) the Work and for which the | ||||||
|  |       editorial revisions, annotations, elaborations, or other modifications | ||||||
|  |       represent, as a whole, an original work of authorship. For the purposes | ||||||
|  |       of this License, Derivative Works shall not include works that remain | ||||||
|  |       separable from, or merely link (or bind by name) to the interfaces of, | ||||||
|  |       the Work and Derivative Works thereof. | ||||||
|  |  | ||||||
|  |       "Contribution" shall mean any work of authorship, including | ||||||
|  |       the original version of the Work and any modifications or additions | ||||||
|  |       to that Work or Derivative Works thereof, that is intentionally | ||||||
|  |       submitted to Licensor for inclusion in the Work by the copyright owner | ||||||
|  |       or by an individual or Legal Entity authorized to submit on behalf of | ||||||
|  |       the copyright owner. For the purposes of this definition, "submitted" | ||||||
|  |       means any form of electronic, verbal, or written communication sent | ||||||
|  |       to the Licensor or its representatives, including but not limited to | ||||||
|  |       communication on electronic mailing lists, source code control systems, | ||||||
|  |       and issue tracking systems that are managed by, or on behalf of, the | ||||||
|  |       Licensor for the purpose of discussing and improving the Work, but | ||||||
|  |       excluding communication that is conspicuously marked or otherwise | ||||||
|  |       designated in writing by the copyright owner as "Not a Contribution." | ||||||
|  |  | ||||||
|  |       "Contributor" shall mean Licensor and any individual or Legal Entity | ||||||
|  |       on behalf of whom a Contribution has been received by Licensor and | ||||||
|  |       subsequently incorporated within the Work. | ||||||
|  |  | ||||||
|  |    2. Grant of Copyright License. Subject to the terms and conditions of | ||||||
|  |       this License, each Contributor hereby grants to You a perpetual, | ||||||
|  |       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||||
|  |       copyright license to reproduce, prepare Derivative Works of, | ||||||
|  |       publicly display, publicly perform, sublicense, and distribute the | ||||||
|  |       Work and such Derivative Works in Source or Object form. | ||||||
|  |  | ||||||
|  |    3. Grant of Patent License. Subject to the terms and conditions of | ||||||
|  |       this License, each Contributor hereby grants to You a perpetual, | ||||||
|  |       worldwide, non-exclusive, no-charge, royalty-free, irrevocable | ||||||
|  |       (except as stated in this section) patent license to make, have made, | ||||||
|  |       use, offer to sell, sell, import, and otherwise transfer the Work, | ||||||
|  |       where such license applies only to those patent claims licensable | ||||||
|  |       by such Contributor that are necessarily infringed by their | ||||||
|  |       Contribution(s) alone or by combination of their Contribution(s) | ||||||
|  |       with the Work to which such Contribution(s) was submitted. If You | ||||||
|  |       institute patent litigation against any entity (including a | ||||||
|  |       cross-claim or counterclaim in a lawsuit) alleging that the Work | ||||||
|  |       or a Contribution incorporated within the Work constitutes direct | ||||||
|  |       or contributory patent infringement, then any patent licenses | ||||||
|  |       granted to You under this License for that Work shall terminate | ||||||
|  |       as of the date such litigation is filed. | ||||||
|  |  | ||||||
|  |    4. Redistribution. You may reproduce and distribute copies of the | ||||||
|  |       Work or Derivative Works thereof in any medium, with or without | ||||||
|  |       modifications, and in Source or Object form, provided that You | ||||||
|  |       meet the following conditions: | ||||||
|  |  | ||||||
|  |       (a) You must give any other recipients of the Work or | ||||||
|  |           Derivative Works a copy of this License; and | ||||||
|  |  | ||||||
|  |       (b) You must cause any modified files to carry prominent notices | ||||||
|  |           stating that You changed the files; and | ||||||
|  |  | ||||||
|  |       (c) You must retain, in the Source form of any Derivative Works | ||||||
|  |           that You distribute, all copyright, patent, trademark, and | ||||||
|  |           attribution notices from the Source form of the Work, | ||||||
|  |           excluding those notices that do not pertain to any part of | ||||||
|  |           the Derivative Works; and | ||||||
|  |  | ||||||
|  |       (d) If the Work includes a "NOTICE" text file as part of its | ||||||
|  |           distribution, then any Derivative Works that You distribute must | ||||||
|  |           include a readable copy of the attribution notices contained | ||||||
|  |           within such NOTICE file, excluding those notices that do not | ||||||
|  |           pertain to any part of the Derivative Works, in at least one | ||||||
|  |           of the following places: within a NOTICE text file distributed | ||||||
|  |           as part of the Derivative Works; within the Source form or | ||||||
|  |           documentation, if provided along with the Derivative Works; or, | ||||||
|  |           within a display generated by the Derivative Works, if and | ||||||
|  |           wherever such third-party notices normally appear. The contents | ||||||
|  |           of the NOTICE file are for informational purposes only and | ||||||
|  |           do not modify the License. You may add Your own attribution | ||||||
|  |           notices within Derivative Works that You distribute, alongside | ||||||
|  |           or as an addendum to the NOTICE text from the Work, provided | ||||||
|  |           that such additional attribution notices cannot be construed | ||||||
|  |           as modifying the License. | ||||||
|  |  | ||||||
|  |       You may add Your own copyright statement to Your modifications and | ||||||
|  |       may provide additional or different license terms and conditions | ||||||
|  |       for use, reproduction, or distribution of Your modifications, or | ||||||
|  |       for any such Derivative Works as a whole, provided Your use, | ||||||
|  |       reproduction, and distribution of the Work otherwise complies with | ||||||
|  |       the conditions stated in this License. | ||||||
|  |  | ||||||
|  |    5. Submission of Contributions. Unless You explicitly state otherwise, | ||||||
|  |       any Contribution intentionally submitted for inclusion in the Work | ||||||
|  |       by You to the Licensor shall be under the terms and conditions of | ||||||
|  |       this License, without any additional terms or conditions. | ||||||
|  |       Notwithstanding the above, nothing herein shall supersede or modify | ||||||
|  |       the terms of any separate license agreement you may have executed | ||||||
|  |       with Licensor regarding such Contributions. | ||||||
|  |  | ||||||
|  |    6. Trademarks. This License does not grant permission to use the trade | ||||||
|  |       names, trademarks, service marks, or product names of the Licensor, | ||||||
|  |       except as required for reasonable and customary use in describing the | ||||||
|  |       origin of the Work and reproducing the content of the NOTICE file. | ||||||
|  |  | ||||||
|  |    7. Disclaimer of Warranty. Unless required by applicable law or | ||||||
|  |       agreed to in writing, Licensor provides the Work (and each | ||||||
|  |       Contributor provides its Contributions) on an "AS IS" BASIS, | ||||||
|  |       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||||||
|  |       implied, including, without limitation, any warranties or conditions | ||||||
|  |       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | ||||||
|  |       PARTICULAR PURPOSE. You are solely responsible for determining the | ||||||
|  |       appropriateness of using or redistributing the Work and assume any | ||||||
|  |       risks associated with Your exercise of permissions under this License. | ||||||
|  |  | ||||||
|  |    8. Limitation of Liability. In no event and under no legal theory, | ||||||
|  |       whether in tort (including negligence), contract, or otherwise, | ||||||
|  |       unless required by applicable law (such as deliberate and grossly | ||||||
|  |       negligent acts) or agreed to in writing, shall any Contributor be | ||||||
|  |       liable to You for damages, including any direct, indirect, special, | ||||||
|  |       incidental, or consequential damages of any character arising as a | ||||||
|  |       result of this License or out of the use or inability to use the | ||||||
|  |       Work (including but not limited to damages for loss of goodwill, | ||||||
|  |       work stoppage, computer failure or malfunction, or any and all | ||||||
|  |       other commercial damages or losses), even if such Contributor | ||||||
|  |       has been advised of the possibility of such damages. | ||||||
|  |  | ||||||
|  |    9. Accepting Warranty or Additional Liability. While redistributing | ||||||
|  |       the Work or Derivative Works thereof, You may choose to offer, | ||||||
|  |       and charge a fee for, acceptance of support, warranty, indemnity, | ||||||
|  |       or other liability obligations and/or rights consistent with this | ||||||
|  |       License. However, in accepting such obligations, You may act only | ||||||
|  |       on Your own behalf and on Your sole responsibility, not on behalf | ||||||
|  |       of any other Contributor, and only if You agree to indemnify, | ||||||
|  |       defend, and hold each Contributor harmless for any liability | ||||||
|  |       incurred by, or claims asserted against, such Contributor by reason | ||||||
|  |       of your accepting any such warranty or additional liability. | ||||||
|  |  | ||||||
|  |    END OF TERMS AND CONDITIONS | ||||||
|  |  | ||||||
|  |    Copyright 2015-2016 Vincent Demeester | ||||||
|  |  | ||||||
|  |    Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |    you may not use this file except in compliance with the License. | ||||||
|  |    You may obtain a copy of the License at | ||||||
|  |  | ||||||
|  |        https://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  |  | ||||||
|  |    Unless required by applicable law or agreed to in writing, software | ||||||
|  |    distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |    See the License for the specific language governing permissions and | ||||||
|  |    limitations under the License. | ||||||
							
								
								
									
										37
									
								
								vendor/src/github.com/vdemeester/shakers/Makefile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/src/github.com/vdemeester/shakers/Makefile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | .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: all | ||||||
|  |  | ||||||
|  | all: build | ||||||
|  | 	$(DOCKER_RUN_SHAKERS) ./script/make.sh | ||||||
|  |  | ||||||
|  | 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 | ||||||
|  |  | ||||||
							
								
								
									
										30
									
								
								vendor/src/github.com/vdemeester/shakers/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								vendor/src/github.com/vdemeester/shakers/README.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | # Shakers | ||||||
|  | 🐹 + 🐙 = 😽 [](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 `glide` 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 | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | ### Using glide and `GO15VENDOREXPERIMENT` | ||||||
|  |  | ||||||
|  | - Get the dependencies with `glide up` (or use `go get` but you have no garantuees over the version of the dependencies) | ||||||
|  | - If you're using glide (and not standard `go get`) export `GO15VENDOREXPERIMENT` with `export GO15VENDOREXPERIMENT=1` | ||||||
|  | - Run tests with `go test .` | ||||||
							
								
								
									
										46
									
								
								vendor/src/github.com/vdemeester/shakers/bool.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								vendor/src/github.com/vdemeester/shakers/bool.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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, "" | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								vendor/src/github.com/vdemeester/shakers/circle.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/src/github.com/vdemeester/shakers/circle.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | machine: | ||||||
|  |   services: | ||||||
|  |     - docker | ||||||
|  |  | ||||||
|  | dependencies: | ||||||
|  |   override: | ||||||
|  |     - make validate | ||||||
|  |  | ||||||
|  | test: | ||||||
|  |   override: | ||||||
|  |     - make test-unit | ||||||
							
								
								
									
										310
									
								
								vendor/src/github.com/vdemeester/shakers/common.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										310
									
								
								vendor/src/github.com/vdemeester/shakers/common.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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." | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										4
									
								
								vendor/src/github.com/vdemeester/shakers/glide.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								vendor/src/github.com/vdemeester/shakers/glide.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | |||||||
|  | package: main | ||||||
|  | import: | ||||||
|  |   - package: github.com/go-check/check | ||||||
|  |     ref:     11d3bc7aa68e238947792f30573146a3231fc0f1 | ||||||
							
								
								
									
										168
									
								
								vendor/src/github.com/vdemeester/shakers/string.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								vendor/src/github.com/vdemeester/shakers/string.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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()." | ||||||
|  | } | ||||||
							
								
								
									
										234
									
								
								vendor/src/github.com/vdemeester/shakers/time.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								vendor/src/github.com/vdemeester/shakers/time.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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 | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user
	 Kenfe-Mickael Laventure
					Kenfe-Mickael Laventure