migrate from govendor to dep
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.iml
|
||||
/.idea
|
||||
coverage.out
|
||||
+119
@@ -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
@@ -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
@@ -1,3 +0,0 @@
|
||||
#ignore
|
||||
-timeout=1s
|
||||
-coverpkg=github.com/smartystreets/assertions,github.com/smartystreets/assertions/internal/oglematchers
|
||||
+3
-1
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
go-render: A verbose recursive Go type-to-string conversion library.
|
||||
====================================================================
|
||||
|
||||
[](https://godoc.org/github.com/luci/go-render)
|
||||
[](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.
|
||||
+26
@@ -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
|
||||
-70
@@ -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
|
||||
}
|
||||
-32
@@ -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
|
||||
}
|
||||
-91
@@ -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
|
||||
}
|
||||
-51
@@ -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())
|
||||
}
|
||||
Generated
Vendored
-37
@@ -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))
|
||||
}
|
||||
-46
@@ -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("")
|
||||
}
|
||||
-134
@@ -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("")
|
||||
}
|
||||
Generated
Vendored
-69
@@ -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
|
||||
}
|
||||
-43
@@ -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
|
||||
}
|
||||
-74
@@ -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
|
||||
}
|
||||
-65
@@ -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())
|
||||
}
|
||||
Generated
Vendored
+1
-1
@@ -23,7 +23,7 @@ func transformDescription(m Matcher, newDesc string) Matcher {
|
||||
}
|
||||
|
||||
type transformDescriptionMatcher struct {
|
||||
desc string
|
||||
desc string
|
||||
wrappedMatcher Matcher
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -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
@@ -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
@@ -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
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user