migrate from govendor to dep

This commit is contained in:
bergquist
2018-01-19 09:48:15 +01:00
parent 5bb22b836d
commit e023f79c5a
7349 changed files with 3153302 additions and 64302 deletions
+5
View File
@@ -0,0 +1,5 @@
.DS_Store
Thumbs.db
*.iml
/.idea
coverage.out
+119
View File
@@ -0,0 +1,119 @@
package assert
import (
"fmt"
"io"
"os"
"reflect"
"runtime"
"strings"
"github.com/smartystreets/logging"
)
// Result contains a single assertion failure as an error.
// You should not create a Result directly, use So instead.
// Once created, a Result is read-only and only allows
// queries using the provided methods.
type Result struct {
invocation string
err error
stdout io.Writer
logger *logging.Logger
}
// So is a convenience function (as opposed to an inconvenience function?)
// for running assertions on arbitrary arguments in any context. It allows you to perform
// assertion-like behavior and decide what happens in the event of a failure.
// It is a variant of assertions.So in every respect except its return value.
// In this case, the return value is a *Result which possesses several of its
// own convenience methods:
//
// fmt.Println(assert.So(1, should.Equal, 1)) // Calls String() and prints the representation of the assertion.
// assert.So(1, should.Equal, 1).Println() // Calls fmt.Print with the failure message and file:line header.
// assert.So(1, should.Equal, 1).Log() // Calls log.Print with the failure message and file:line header.
// assert.So(1, should.Equal, 1).Panic() // Calls log.Panic with the failure message and file:line header.
// assert.So(1, should.Equal, 1).Fatal() // Calls log.Fatal with the failure message and file:line header.
// if err := assert.So(1, should.Equal, 1).Error(); err != nil {
// // Allows custom handling of the error, which will include the failure message and file:line header.
// }
func So(actual interface{}, assert assertion, expected ...interface{}) *Result {
result := new(Result)
result.stdout = os.Stdout
result.invocation = fmt.Sprintf("So(actual: %v, %v, expected: %v)", actual, assertionName(assert), expected)
if failure := assert(actual, expected...); len(failure) > 0 {
_, file, line, _ := runtime.Caller(1)
result.err = fmt.Errorf("Assertion failure at %s:%d\n%s", file, line, failure)
}
return result
}
func assertionName(i interface{}) string {
functionAddress := runtime.FuncForPC(reflect.ValueOf(i).Pointer())
fullNameStartingWithPackage := functionAddress.Name()
parts := strings.Split(fullNameStartingWithPackage, "/")
baseName := parts[len(parts)-1]
return strings.Replace(baseName, "assertions.Should", "should.", 1)
}
// Failed returns true if the assertion failed, false if it passed.
func (this *Result) Failed() bool {
return !this.Passed()
}
// Passed returns true if the assertion passed, false if it failed.
func (this *Result) Passed() bool {
return this.err == nil
}
// Error returns the error representing an assertion failure, which is nil in the case of a passed assertion.
func (this *Result) Error() error {
return this.err
}
// String implements fmt.Stringer.
// It returns the error as a string in the case of an assertion failure.
// Unlike other methods defined herein, if returns a non-empty
// representation of the assertion as confirmation of success.
func (this *Result) String() string {
if this.Passed() {
return fmt.Sprintf("✔ %s", this.invocation)
} else {
return fmt.Sprintf("✘ %s\n%v", this.invocation, this.Error())
}
}
// Println calls fmt.Println in the case of an assertion failure.
func (this *Result) Println() *Result {
if this.Failed() {
fmt.Fprintln(this.stdout, this)
}
return this
}
// Log calls log.Print in the case of an assertion failure.
func (this *Result) Log() *Result {
if this.Failed() {
this.logger.Print(this)
}
return this
}
// Panic calls log.Panic in the case of an assertion failure.
func (this *Result) Panic() *Result {
if this.Failed() {
this.logger.Panic(this)
}
return this
}
// Fatal calls log.Fatal in the case of an assertion failure.
func (this *Result) Fatal() *Result {
if this.Failed() {
this.logger.Fatal(this)
}
return this
}
// assertion is a copy of github.com/smartystreets/assertions.assertion.
type assertion func(actual interface{}, expected ...interface{}) string
+49
View File
@@ -0,0 +1,49 @@
package main
import (
"fmt"
"github.com/smartystreets/assertions/assert"
"github.com/smartystreets/assertions/should"
)
func main() {
exampleUsage(assert.So(1, should.Equal, 1)) // pass
exampleUsage(assert.So(1, should.Equal, 2)) // fail
}
func exampleUsage(result *assert.Result) {
if result.Passed() {
fmt.Println("The assertion passed:", result)
} else if result.Failed() {
fmt.Println("The assertion failed:", result)
}
fmt.Print("\nAbout to see result.Error()...\n\n")
if err := result.Error(); err != nil {
fmt.Println(err)
}
fmt.Print("\nAbout to see result.Println()...\n\n")
result.Println()
fmt.Print("\nAbout to see result.Log()...\n\n")
result.Log()
fmt.Print("\nAbout to see result.Panic()...\n\n")
defer func() {
recover()
fmt.Print("\nAbout to see result.Fatal()...\n\n")
result.Fatal()
fmt.Print("---------------------------------------------------------------\n\n")
}()
result.Panic()
}
-3
View File
@@ -1,3 +0,0 @@
#ignore
-timeout=1s
-coverpkg=github.com/smartystreets/assertions,github.com/smartystreets/assertions/internal/oglematchers
+3 -1
View File
@@ -26,7 +26,7 @@ var serializer Serializer = new(noopSerializer)
// are very helpful and can be rendered in a DIFF view. In that case, this function
// will be called with a true value to enable the JSON serialization. By default,
// the assertions in this package will not serializer a JSON result, making
// standalone ussage more convenient.
// standalone usage more convenient.
func GoConveyMode(yes bool) {
if yes {
serializer = newSerializer()
@@ -82,6 +82,8 @@ func (this *Assertion) So(actual interface{}, assert assertion, expected ...inte
// log.Println(message)
// }
//
// For an alternative implementation of So (that provides more flexible return options)
// see the `So` function in the package at github.com/smartystreets/assertions/assert.
func So(actual interface{}, assert assertion, expected ...interface{}) (bool, string) {
if result := so(actual, assert, expected...); len(result) == 0 {
return true, result
+75
View File
@@ -0,0 +1,75 @@
package assertions
import "reflect"
type equalityMethodSpecification struct {
a interface{}
b interface{}
aType reflect.Type
bType reflect.Type
equalMethod reflect.Value
}
func newEqualityMethodSpecification(a, b interface{}) *equalityMethodSpecification {
return &equalityMethodSpecification{
a: a,
b: b,
}
}
func (this *equalityMethodSpecification) IsSatisfied() bool {
if !this.bothAreSameType() {
return false
}
if !this.typeHasEqualMethod() {
return false
}
if !this.equalMethodReceivesSameTypeForComparison() {
return false
}
if !this.equalMethodReturnsBool() {
return false
}
return true
}
func (this *equalityMethodSpecification) bothAreSameType() bool {
this.aType = reflect.TypeOf(this.a)
if this.aType == nil {
return false
}
if this.aType.Kind() == reflect.Ptr {
this.aType = this.aType.Elem()
}
this.bType = reflect.TypeOf(this.b)
return this.aType == this.bType
}
func (this *equalityMethodSpecification) typeHasEqualMethod() bool {
aInstance := reflect.ValueOf(this.a)
this.equalMethod = aInstance.MethodByName("Equal")
return this.equalMethod != reflect.Value{}
}
func (this *equalityMethodSpecification) equalMethodReceivesSameTypeForComparison() bool {
signature := this.equalMethod.Type()
return signature.NumIn() == 1 && signature.In(0) == this.aType
}
func (this *equalityMethodSpecification) equalMethodReturnsBool() bool {
signature := this.equalMethod.Type()
return signature.NumOut() == 1 && signature.Out(0) == reflect.TypeOf(true)
}
func (this *equalityMethodSpecification) AreEqual() bool {
a := reflect.ValueOf(this.a)
b := reflect.ValueOf(this.b)
return areEqual(a, b) && areEqual(b, a)
}
func areEqual(receiver reflect.Value, argument reflect.Value) bool {
equalMethod := receiver.MethodByName("Equal")
argumentList := []reflect.Value{argument}
result := equalMethod.Call(argumentList)
return result[0].Bool()
}
+20 -14
View File
@@ -7,14 +7,15 @@ import (
"reflect"
"strings"
"github.com/smartystreets/assertions/internal/oglematchers"
"github.com/smartystreets/assertions/internal/go-render/render"
"github.com/smartystreets/assertions/internal/oglematchers"
)
// default acceptable delta for ShouldAlmostEqual
const defaultDelta = 0.0000000001
// ShouldEqual receives exactly two parameters and does an equality check.
// ShouldEqual receives exactly two parameters and does an equality check
// using the following semantics:
// 1. If the expected and actual values implement an Equal method in the form
// `func (this T) Equal(that T) bool` then call the method. If true, they are equal.
// 2. The expected and actual values are judged equal or not by oglematchers.Equals.
func ShouldEqual(actual interface{}, expected ...interface{}) string {
if message := need(1, expected); message != success {
return message
@@ -25,10 +26,17 @@ func shouldEqual(actual, expected interface{}) (message string) {
defer func() {
if r := recover(); r != nil {
message = serializer.serialize(expected, actual, fmt.Sprintf(shouldHaveBeenEqual, expected, actual))
return
}
}()
if specification := newEqualityMethodSpecification(expected, actual); specification.IsSatisfied() {
if specification.AreEqual() {
return success
} else {
message = fmt.Sprintf(shouldHaveBeenEqual, expected, actual)
return serializer.serialize(expected, actual, message)
}
}
if matchError := oglematchers.Equals(expected).Matches(actual); matchError != nil {
expectedSyntax := fmt.Sprintf("%v", expected)
actualSyntax := fmt.Sprintf("%v", actual)
@@ -37,14 +45,14 @@ func shouldEqual(actual, expected interface{}) (message string) {
} else {
message = fmt.Sprintf(shouldHaveBeenEqual, expected, actual)
}
message = serializer.serialize(expected, actual, message)
return
return serializer.serialize(expected, actual, message)
}
return success
}
// ShouldNotEqual receives exactly two parameters and does an inequality check.
// See ShouldEqual for details on how equality is determined.
func ShouldNotEqual(actual interface{}, expected ...interface{}) string {
if fail := need(1, expected); fail != success {
return fail
@@ -95,7 +103,7 @@ func cleanAlmostEqualInput(actual interface{}, expected ...interface{}) (float64
delta, err := getFloat(expected[1])
if err != nil {
return 0.0, 0.0, 0.0, "delta must be a numerical type"
return 0.0, 0.0, 0.0, "The delta value " + err.Error()
}
deltaFloat = delta
@@ -104,15 +112,13 @@ func cleanAlmostEqualInput(actual interface{}, expected ...interface{}) (float64
}
actualFloat, err := getFloat(actual)
if err != nil {
return 0.0, 0.0, 0.0, err.Error()
return 0.0, 0.0, 0.0, "The actual value " + err.Error()
}
expectedFloat, err := getFloat(expected[0])
if err != nil {
return 0.0, 0.0, 0.0, err.Error()
return 0.0, 0.0, 0.0, "The comparison value " + err.Error()
}
return actualFloat, expectedFloat, deltaFloat, ""
@@ -139,7 +145,7 @@ func getFloat(num interface{}) (float64, error) {
numKind == reflect.Float64 {
return numValue.Float(), nil
} else {
return 0.0, errors.New("must be a numerical type, but was " + numKind.String())
return 0.0, errors.New("must be a numerical type, but was: " + numKind.String())
}
}
+8
View File
@@ -6,6 +6,7 @@ const (
success = ""
needExactValues = "This assertion requires exactly %d comparison values (you provided %d)."
needNonEmptyCollection = "This assertion requires at least 1 comparison value (you provided 0)."
needFewerValues = "This assertion allows %d or fewer comparison values (you provided %d)."
)
func need(needed int, expected []interface{}) string {
@@ -21,3 +22,10 @@ func atLeast(minimum int, expected []interface{}) string {
}
return success
}
func atMost(max int, expected []interface{}) string {
if len(expected) > max {
return fmt.Sprintf(needFewerValues, max, len(expected))
}
return success
}
+37
View File
@@ -0,0 +1,37 @@
# This Makefile pulls the latest oglematchers (with dependencies),
# rewrites the imports to match this location,
# and ensures that all the tests pass.
# BTW, things used from oglematchers: Contains, Equals, DeepEquals, GreaterThan, LessThan, GreaterOrEqual, LessOrEqual
test:
go test github.com/smartystreets/assertions/...
update: clear clone rewrite trim
clear:
rm -rf ogle*
rm -rf reqtrace
rm -rf go-render
clone:
git clone https://github.com/jacobsa/oglematchers.git && rm -rf oglematchers/.git
git clone https://github.com/luci/go-render.git && rm -rf go-render/.git
rewrite:
grep -rl --exclude Makefile 'github.com/jacobsa' . | xargs sed -i '' 's#github.com/jacobsa#github.com/smartystreets/assertions/internal#g'
trim:
git checkout oglematchers/contains.go # This file diverged at 6acd0337
rm oglematchers/*_test.go
rm oglematchers/any.go
rm oglematchers/all_of.go
rm oglematchers/elements_are.go
rm oglematchers/error.go
rm oglematchers/has_same_type_as.go
rm oglematchers/has_substr.go
rm oglematchers/identical_to.go
rm oglematchers/matches_regexp.go
rm oglematchers/new_matcher.go
rm oglematchers/panics.go
rm oglematchers/pointee.go
rm go-render/render/*_test.go
@@ -0,0 +1,78 @@
go-render: A verbose recursive Go type-to-string conversion library.
====================================================================
[![GoDoc](https://godoc.org/github.com/luci/go-render?status.svg)](https://godoc.org/github.com/luci/go-render)
[![Build Status](https://travis-ci.org/luci/go-render.svg)](https://travis-ci.org/luci/go-render)
This is not an official Google product.
## Overview
The *render* package implements a more verbose form of the standard Go string
formatter, `fmt.Sprintf("%#v", value)`, adding:
- Pointer recursion. Normally, Go stops at the first pointer and prints its
address. The *render* package will recurse and continue to render pointer
values.
- Recursion loop detection. Recursion is nice, but if a recursion path detects
a loop, *render* will note this and move on.
- Custom type name rendering.
- Deterministic key sorting for `string`- and `int`-keyed maps.
- Testing!
Call `render.Render` and pass it an `interface{}`.
For example:
```Go
type customType int
type testStruct struct {
S string
V *map[string]int
I interface{}
}
a := testStruct{
S: "hello",
V: &map[string]int{"foo": 0, "bar": 1},
I: customType(42),
}
fmt.Println("Render test:")
fmt.Printf("fmt.Printf: %#v\n", a)))
fmt.Printf("render.Render: %s\n", Render(a))
```
Yields:
```
fmt.Printf: render.testStruct{S:"hello", V:(*map[string]int)(0x600dd065), I:42}
render.Render: render.testStruct{S:"hello", V:(*map[string]int){"bar":1, "foo":0}, I:render.customType(42)}
```
This is not intended to be a high-performance library, but it's not terrible
either.
Contributing
------------
* Sign the [Google CLA](https://cla.developers.google.com/clas).
* Make sure your `user.email` and `user.name` are configured in `git config`.
* Install the [pcg](https://github.com/maruel/pre-commit-go) git hook:
`go get -u github.com/maruel/pre-commit-go/cmd/... && pcg`
Run the following to setup the code review tool and create your first review:
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git $HOME/src/depot_tools
export PATH="$PATH:$HOME/src/depot_tools"
cd $GOROOT/github.com/luci/go-render
git checkout -b work origin/master
# hack hack
git commit -a -m "This is awesome\nR=joe@example.com"
# This will ask for your Google Account credentials.
git cl upload -s
# Wait for LGTM over email.
# Check the commit queue box in codereview website.
# Wait for the change to be tested and landed automatically.
Use `git cl help` and `git cl help <cmd>` for more details.
@@ -0,0 +1,26 @@
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Watchlist Rules
# Refer: http://dev.chromium.org/developers/contributing-code/watchlists
{
'WATCHLIST_DEFINITIONS': {
'all': {
'filepath': '.+',
},
},
'WATCHLISTS': {
'all': [
# Add yourself here to get explicitly spammed.
'maruel@chromium.org',
'tandrii+luci-go@chromium.org',
'todd@cloudera.com',
'andrew.wang@cloudera.com',
],
},
}
@@ -0,0 +1,5 @@
*.6
6.out
_obj/
_test/
_testmain.go
@@ -1,70 +0,0 @@
// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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
//
// http://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.
package oglematchers
import (
"strings"
)
// AllOf accepts a set of matchers S and returns a matcher that follows the
// algorithm below when considering a candidate c:
//
// 1. Return true if for every Matcher m in S, m matches c.
//
// 2. Otherwise, if there is a matcher m in S such that m returns a fatal
// error for c, return that matcher's error message.
//
// 3. Otherwise, return false with the error from some wrapped matcher.
//
// This is akin to a logical AND operation for matchers.
func AllOf(matchers ...Matcher) Matcher {
return &allOfMatcher{matchers}
}
type allOfMatcher struct {
wrappedMatchers []Matcher
}
func (m *allOfMatcher) Description() string {
// Special case: the empty set.
if len(m.wrappedMatchers) == 0 {
return "is anything"
}
// Join the descriptions for the wrapped matchers.
wrappedDescs := make([]string, len(m.wrappedMatchers))
for i, wrappedMatcher := range m.wrappedMatchers {
wrappedDescs[i] = wrappedMatcher.Description()
}
return strings.Join(wrappedDescs, ", and ")
}
func (m *allOfMatcher) Matches(c interface{}) (err error) {
for _, wrappedMatcher := range m.wrappedMatchers {
if wrappedErr := wrappedMatcher.Matches(c); wrappedErr != nil {
err = wrappedErr
// If the error is fatal, return immediately with this error.
_, ok := wrappedErr.(*FatalError)
if ok {
return
}
}
}
return
}
@@ -1,32 +0,0 @@
// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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
//
// http://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.
package oglematchers
// Any returns a matcher that matches any value.
func Any() Matcher {
return &anyMatcher{}
}
type anyMatcher struct {
}
func (m *anyMatcher) Description() string {
return "is anything"
}
func (m *anyMatcher) Matches(c interface{}) error {
return nil
}
@@ -1,91 +0,0 @@
// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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
//
// http://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.
package oglematchers
import (
"errors"
"fmt"
"reflect"
"strings"
)
// Given a list of arguments M, ElementsAre returns a matcher that matches
// arrays and slices A where all of the following hold:
//
// * A is the same length as M.
//
// * For each i < len(A) where M[i] is a matcher, A[i] matches M[i].
//
// * For each i < len(A) where M[i] is not a matcher, A[i] matches
// Equals(M[i]).
//
func ElementsAre(M ...interface{}) Matcher {
// Copy over matchers, or convert to Equals(x) for non-matcher x.
subMatchers := make([]Matcher, len(M))
for i, x := range M {
if matcher, ok := x.(Matcher); ok {
subMatchers[i] = matcher
continue
}
subMatchers[i] = Equals(x)
}
return &elementsAreMatcher{subMatchers}
}
type elementsAreMatcher struct {
subMatchers []Matcher
}
func (m *elementsAreMatcher) Description() string {
subDescs := make([]string, len(m.subMatchers))
for i, sm := range m.subMatchers {
subDescs[i] = sm.Description()
}
return fmt.Sprintf("elements are: [%s]", strings.Join(subDescs, ", "))
}
func (m *elementsAreMatcher) Matches(candidates interface{}) error {
// The candidate must be a slice or an array.
v := reflect.ValueOf(candidates)
if v.Kind() != reflect.Slice && v.Kind() != reflect.Array {
return NewFatalError("which is not a slice or array")
}
// The length must be correct.
if v.Len() != len(m.subMatchers) {
return errors.New(fmt.Sprintf("which is of length %d", v.Len()))
}
// Check each element.
for i, subMatcher := range m.subMatchers {
c := v.Index(i)
if matchErr := subMatcher.Matches(c.Interface()); matchErr != nil {
// Return an errors indicating which element doesn't match. If the
// matcher error was fatal, make this one fatal too.
err := errors.New(fmt.Sprintf("whose element %d doesn't match", i))
if _, isFatal := matchErr.(*FatalError); isFatal {
err = NewFatalError(err.Error())
}
return err
}
}
return nil
}
@@ -1,51 +0,0 @@
// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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
//
// http://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.
package oglematchers
// Error returns a matcher that matches non-nil values implementing the
// built-in error interface for whom the return value of Error() matches the
// supplied matcher.
//
// For example:
//
// err := errors.New("taco burrito")
//
// Error(Equals("taco burrito")) // matches err
// Error(HasSubstr("taco")) // matches err
// Error(HasSubstr("enchilada")) // doesn't match err
//
func Error(m Matcher) Matcher {
return &errorMatcher{m}
}
type errorMatcher struct {
wrappedMatcher Matcher
}
func (m *errorMatcher) Description() string {
return "error " + m.wrappedMatcher.Description()
}
func (m *errorMatcher) Matches(c interface{}) error {
// Make sure that c is an error.
e, ok := c.(error)
if !ok {
return NewFatalError("which is not an error")
}
// Pass on the error text to the wrapped matcher.
return m.wrappedMatcher.Matches(e.Error())
}
@@ -1,37 +0,0 @@
// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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
//
// http://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.
package oglematchers
import (
"fmt"
"reflect"
)
// HasSameTypeAs returns a matcher that matches values with exactly the same
// type as the supplied prototype.
func HasSameTypeAs(p interface{}) Matcher {
expected := reflect.TypeOf(p)
pred := func(c interface{}) error {
actual := reflect.TypeOf(c)
if actual != expected {
return fmt.Errorf("which has type %v", actual)
}
return nil
}
return NewMatcher(pred, fmt.Sprintf("has type %v", expected))
}
@@ -1,46 +0,0 @@
// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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
//
// http://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.
package oglematchers
import (
"errors"
"fmt"
"reflect"
"strings"
)
// HasSubstr returns a matcher that matches strings containing s as a
// substring.
func HasSubstr(s string) Matcher {
return NewMatcher(
func(c interface{}) error { return hasSubstr(s, c) },
fmt.Sprintf("has substring \"%s\"", s))
}
func hasSubstr(needle string, c interface{}) error {
v := reflect.ValueOf(c)
if v.Kind() != reflect.String {
return NewFatalError("which is not a string")
}
// Perform the substring search.
haystack := v.String()
if strings.Contains(haystack, needle) {
return nil
}
return errors.New("")
}
@@ -1,134 +0,0 @@
// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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
//
// http://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.
package oglematchers
import (
"errors"
"fmt"
"reflect"
)
// Is the type comparable according to the definition here?
//
// http://weekly.golang.org/doc/go_spec.html#Comparison_operators
//
func isComparable(t reflect.Type) bool {
switch t.Kind() {
case reflect.Array:
return isComparable(t.Elem())
case reflect.Struct:
for i := 0; i < t.NumField(); i++ {
if !isComparable(t.Field(i).Type) {
return false
}
}
return true
case reflect.Slice, reflect.Map, reflect.Func:
return false
}
return true
}
// Should the supplied type be allowed as an argument to IdenticalTo?
func isLegalForIdenticalTo(t reflect.Type) (bool, error) {
// Allow the zero type.
if t == nil {
return true, nil
}
// Reference types are always okay; we compare pointers.
switch t.Kind() {
case reflect.Slice, reflect.Map, reflect.Func, reflect.Chan:
return true, nil
}
// Reject other non-comparable types.
if !isComparable(t) {
return false, errors.New(fmt.Sprintf("%v is not comparable", t))
}
return true, nil
}
// IdenticalTo(x) returns a matcher that matches values v with type identical
// to x such that:
//
// 1. If v and x are of a reference type (slice, map, function, channel), then
// they are either both nil or are references to the same object.
//
// 2. Otherwise, if v and x are not of a reference type but have a valid type,
// then v == x.
//
// If v and x are both the invalid type (which results from the predeclared nil
// value, or from nil interface variables), then the matcher is satisfied.
//
// This function will panic if x is of a value type that is not comparable. For
// example, x cannot be an array of functions.
func IdenticalTo(x interface{}) Matcher {
t := reflect.TypeOf(x)
// Reject illegal arguments.
if ok, err := isLegalForIdenticalTo(t); !ok {
panic("IdenticalTo: " + err.Error())
}
return &identicalToMatcher{x}
}
type identicalToMatcher struct {
x interface{}
}
func (m *identicalToMatcher) Description() string {
t := reflect.TypeOf(m.x)
return fmt.Sprintf("identical to <%v> %v", t, m.x)
}
func (m *identicalToMatcher) Matches(c interface{}) error {
// Make sure the candidate's type is correct.
t := reflect.TypeOf(m.x)
if ct := reflect.TypeOf(c); t != ct {
return NewFatalError(fmt.Sprintf("which is of type %v", ct))
}
// Special case: two values of the invalid type are always identical.
if t == nil {
return nil
}
// Handle reference types.
switch t.Kind() {
case reflect.Slice, reflect.Map, reflect.Func, reflect.Chan:
xv := reflect.ValueOf(m.x)
cv := reflect.ValueOf(c)
if xv.Pointer() == cv.Pointer() {
return nil
}
return errors.New("which is not an identical reference")
}
// Are the values equal?
if m.x == c {
return nil
}
return errors.New("")
}
@@ -1,69 +0,0 @@
// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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
//
// http://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.
package oglematchers
import (
"errors"
"fmt"
"reflect"
"regexp"
)
// MatchesRegexp returns a matcher that matches strings and byte slices whose
// contents match the supplied regular expression. The semantics are those of
// regexp.Match. In particular, that means the match is not implicitly anchored
// to the ends of the string: MatchesRegexp("bar") will match "foo bar baz".
func MatchesRegexp(pattern string) Matcher {
re, err := regexp.Compile(pattern)
if err != nil {
panic("MatchesRegexp: " + err.Error())
}
return &matchesRegexpMatcher{re}
}
type matchesRegexpMatcher struct {
re *regexp.Regexp
}
func (m *matchesRegexpMatcher) Description() string {
return fmt.Sprintf("matches regexp \"%s\"", m.re.String())
}
func (m *matchesRegexpMatcher) Matches(c interface{}) (err error) {
v := reflect.ValueOf(c)
isString := v.Kind() == reflect.String
isByteSlice := v.Kind() == reflect.Slice && v.Elem().Kind() == reflect.Uint8
err = errors.New("")
switch {
case isString:
if m.re.MatchString(v.String()) {
err = nil
}
case isByteSlice:
if m.re.Match(v.Bytes()) {
err = nil
}
default:
err = NewFatalError("which is not a string or []byte")
}
return
}
@@ -1,43 +0,0 @@
// Copyright 2015 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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
//
// http://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.
package oglematchers
// Create a matcher with the given description and predicate function, which
// will be invoked to handle calls to Matchers.
//
// Using this constructor may be a convenience over defining your own type that
// implements Matcher if you do not need any logic in your Description method.
func NewMatcher(
predicate func(interface{}) error,
description string) Matcher {
return &predicateMatcher{
predicate: predicate,
description: description,
}
}
type predicateMatcher struct {
predicate func(interface{}) error
description string
}
func (pm *predicateMatcher) Matches(c interface{}) error {
return pm.predicate(c)
}
func (pm *predicateMatcher) Description() string {
return pm.description
}
@@ -1,74 +0,0 @@
// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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
//
// http://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.
package oglematchers
import (
"errors"
"fmt"
"reflect"
)
// Panics matches zero-arg functions which, when invoked, panic with an error
// that matches the supplied matcher.
//
// NOTE(jacobsa): This matcher cannot detect the case where the function panics
// using panic(nil), by design of the language. See here for more info:
//
// http://goo.gl/9aIQL
//
func Panics(m Matcher) Matcher {
return &panicsMatcher{m}
}
type panicsMatcher struct {
wrappedMatcher Matcher
}
func (m *panicsMatcher) Description() string {
return "panics with: " + m.wrappedMatcher.Description()
}
func (m *panicsMatcher) Matches(c interface{}) (err error) {
// Make sure c is a zero-arg function.
v := reflect.ValueOf(c)
if v.Kind() != reflect.Func || v.Type().NumIn() != 0 {
err = NewFatalError("which is not a zero-arg function")
return
}
// Call the function and check its panic error.
defer func() {
if e := recover(); e != nil {
err = m.wrappedMatcher.Matches(e)
// Set a clearer error message if the matcher said no.
if err != nil {
wrappedClause := ""
if err.Error() != "" {
wrappedClause = ", " + err.Error()
}
err = errors.New(fmt.Sprintf("which panicked with: %v%s", e, wrappedClause))
}
}
}()
v.Call([]reflect.Value{})
// If we get here, the function didn't panic.
err = errors.New("which didn't panic")
return
}
@@ -1,65 +0,0 @@
// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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
//
// http://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.
package oglematchers
import (
"errors"
"fmt"
"reflect"
)
// Return a matcher that matches non-nil pointers whose pointee matches the
// wrapped matcher.
func Pointee(m Matcher) Matcher {
return &pointeeMatcher{m}
}
type pointeeMatcher struct {
wrapped Matcher
}
func (m *pointeeMatcher) Matches(c interface{}) (err error) {
// Make sure the candidate is of the appropriate type.
cv := reflect.ValueOf(c)
if !cv.IsValid() || cv.Kind() != reflect.Ptr {
return NewFatalError("which is not a pointer")
}
// Make sure the candidate is non-nil.
if cv.IsNil() {
return NewFatalError("")
}
// Defer to the wrapped matcher. Fix up empty errors so that failure messages
// are more helpful than just printing a pointer for "Actual".
pointee := cv.Elem().Interface()
err = m.wrapped.Matches(pointee)
if err != nil && err.Error() == "" {
s := fmt.Sprintf("whose pointee is %v", pointee)
if _, ok := err.(*FatalError); ok {
err = NewFatalError(s)
} else {
err = errors.New(s)
}
}
return err
}
func (m *pointeeMatcher) Description() string {
return fmt.Sprintf("pointee(%s)", m.wrapped.Description())
}
@@ -23,7 +23,7 @@ func transformDescription(m Matcher, newDesc string) Matcher {
}
type transformDescriptionMatcher struct {
desc string
desc string
wrappedMatcher Matcher
}
+3
View File
@@ -77,6 +77,9 @@ const ( // type checking
shouldNotHaveImplemented = "Expected '%v'\nto NOT implement '%v'\n(but it did)!"
shouldCompareWithInterfacePointer = "The expected value must be a pointer to an interface type (eg. *fmt.Stringer)"
shouldNotBeNilActual = "The actual value was 'nil' and should be a value or a pointer to a value!"
shouldBeError = "Expected an error value (but was '%v' instead)!"
shouldBeErrorInvalidComparisonValue = "The final argument to this assertion must be a string or an error value (you provided: '%v')."
)
const ( // time comparisons
+4 -10
View File
@@ -20,10 +20,7 @@ func (self *failureSerializer) serializeDetailed(expected, actual interface{}, m
Expected: render.Render(expected),
Actual: render.Render(actual),
}
serialized, err := json.Marshal(view)
if err != nil {
return message
}
serialized, _ := json.Marshal(view)
return string(serialized)
}
@@ -33,10 +30,7 @@ func (self *failureSerializer) serialize(expected, actual interface{}, message s
Expected: fmt.Sprintf("%+v", expected),
Actual: fmt.Sprintf("%+v", actual),
}
serialized, err := json.Marshal(view)
if err != nil {
return message
}
serialized, _ := json.Marshal(view)
return string(serialized)
}
@@ -57,8 +51,8 @@ type FailureView struct {
///////////////////////////////////////////////////////
// noopSerializer just gives back the original message. This is useful when we are using
// the assertions from a context other than the web UI, that requires the JSON structure
// provided by the failureSerializer.
// the assertions from a context other than the GoConvey Web UI, that requires the JSON
// structure provided by the failureSerializer.
type noopSerializer struct{}
func (self *noopSerializer) serialize(expected, actual interface{}, message string) string {
+75
View File
@@ -0,0 +1,75 @@
// package should is simply a rewording of the assertion
// functions in the assertions package.
package should
import "github.com/smartystreets/assertions"
var (
Equal = assertions.ShouldEqual
NotEqual = assertions.ShouldNotEqual
AlmostEqual = assertions.ShouldAlmostEqual
NotAlmostEqual = assertions.ShouldNotAlmostEqual
Resemble = assertions.ShouldResemble
NotResemble = assertions.ShouldNotResemble
PointTo = assertions.ShouldPointTo
NotPointTo = assertions.ShouldNotPointTo
BeNil = assertions.ShouldBeNil
NotBeNil = assertions.ShouldNotBeNil
BeTrue = assertions.ShouldBeTrue
BeFalse = assertions.ShouldBeFalse
BeZeroValue = assertions.ShouldBeZeroValue
BeGreaterThan = assertions.ShouldBeGreaterThan
BeGreaterThanOrEqualTo = assertions.ShouldBeGreaterThanOrEqualTo
BeLessThan = assertions.ShouldBeLessThan
BeLessThanOrEqualTo = assertions.ShouldBeLessThanOrEqualTo
BeBetween = assertions.ShouldBeBetween
NotBeBetween = assertions.ShouldNotBeBetween
BeBetweenOrEqual = assertions.ShouldBeBetweenOrEqual
NotBeBetweenOrEqual = assertions.ShouldNotBeBetweenOrEqual
Contain = assertions.ShouldContain
NotContain = assertions.ShouldNotContain
ContainKey = assertions.ShouldContainKey
NotContainKey = assertions.ShouldNotContainKey
BeIn = assertions.ShouldBeIn
NotBeIn = assertions.ShouldNotBeIn
BeEmpty = assertions.ShouldBeEmpty
NotBeEmpty = assertions.ShouldNotBeEmpty
HaveLength = assertions.ShouldHaveLength
StartWith = assertions.ShouldStartWith
NotStartWith = assertions.ShouldNotStartWith
EndWith = assertions.ShouldEndWith
NotEndWith = assertions.ShouldNotEndWith
BeBlank = assertions.ShouldBeBlank
NotBeBlank = assertions.ShouldNotBeBlank
ContainSubstring = assertions.ShouldContainSubstring
NotContainSubstring = assertions.ShouldNotContainSubstring
EqualWithout = assertions.ShouldEqualWithout
EqualTrimSpace = assertions.ShouldEqualTrimSpace
Panic = assertions.ShouldPanic
NotPanic = assertions.ShouldNotPanic
PanicWith = assertions.ShouldPanicWith
NotPanicWith = assertions.ShouldNotPanicWith
HaveSameTypeAs = assertions.ShouldHaveSameTypeAs
NotHaveSameTypeAs = assertions.ShouldNotHaveSameTypeAs
Implement = assertions.ShouldImplement
NotImplement = assertions.ShouldNotImplement
HappenBefore = assertions.ShouldHappenBefore
HappenOnOrBefore = assertions.ShouldHappenOnOrBefore
HappenAfter = assertions.ShouldHappenAfter
HappenOnOrAfter = assertions.ShouldHappenOnOrAfter
HappenBetween = assertions.ShouldHappenBetween
HappenOnOrBetween = assertions.ShouldHappenOnOrBetween
NotHappenOnOrBetween = assertions.ShouldNotHappenOnOrBetween
HappenWithin = assertions.ShouldHappenWithin
NotHappenWithin = assertions.ShouldNotHappenWithin
BeChronological = assertions.ShouldBeChronological
BeError = assertions.ShouldBeError
)
+28 -6
View File
@@ -14,9 +14,10 @@ func ShouldHaveSameTypeAs(actual interface{}, expected ...interface{}) string {
first := reflect.TypeOf(actual)
second := reflect.TypeOf(expected[0])
if equal := ShouldEqual(first, second); equal != success {
if first != second {
return serializer.serialize(second, first, fmt.Sprintf(shouldHaveBeenA, actual, second, first))
}
return success
}
@@ -29,7 +30,7 @@ func ShouldNotHaveSameTypeAs(actual interface{}, expected ...interface{}) string
first := reflect.TypeOf(actual)
second := reflect.TypeOf(expected[0])
if equal := ShouldEqual(first, second); equal == success {
if (actual == nil && expected[0] == nil) || first == second {
return fmt.Sprintf(shouldNotHaveBeenA, actual, second)
}
return success
@@ -65,10 +66,6 @@ func ShouldImplement(actual interface{}, expectedList ...interface{}) string {
expectedInterface := expectedType.Elem()
if actualType == nil {
return fmt.Sprintf(shouldHaveImplemented, expectedInterface, actual)
}
if !actualType.Implements(expectedInterface) {
return fmt.Sprintf(shouldHaveImplemented, expectedInterface, actualType)
}
@@ -110,3 +107,28 @@ func ShouldNotImplement(actual interface{}, expectedList ...interface{}) string
}
return success
}
// ShouldBeError asserts that the first argument implements the error interface.
// It also compares the first argument against the second argument if provided
// (which must be an error message string or another error value).
func ShouldBeError(actual interface{}, expected ...interface{}) string {
if fail := atMost(1, expected); fail != success {
return fail
}
if !isError(actual) {
return fmt.Sprintf(shouldBeError, reflect.TypeOf(actual))
}
if len(expected) == 0 {
return success
}
if expected := expected[0]; !isString(expected) && !isError(expected) {
return fmt.Sprintf(shouldBeErrorInvalidComparisonValue, reflect.TypeOf(expected))
}
return ShouldEqual(fmt.Sprint(actual), fmt.Sprint(expected[0]))
}
func isString(value interface{}) bool { _, ok := value.(string); return ok }
func isError(value interface{}) bool { _, ok := value.(error); return ok }