diff --git a/.gitignore b/.gitignore index 5aacdb7cc..9569656a7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ *.a *.so +# Binaries +codegen + # Folders _obj _test diff --git a/.travis.gogenerate.sh b/.travis.gogenerate.sh index 161b449cd..8f5366b35 100755 --- a/.travis.gogenerate.sh +++ b/.travis.gogenerate.sh @@ -1,10 +1,14 @@ #!/bin/bash +set -e +set -o pipefail + if [[ "$TRAVIS_GO_VERSION" =~ ^1\.[45](\..*)?$ ]]; then exit 0 fi go get github.com/ernesto-jimenez/gogen/imports +go build -o codegen ./_codegen go generate ./... if [ -n "$(git diff)" ]; then echo "Go generate had not been run" diff --git a/_codegen/importer_new.go b/_codegen/importer_new.go new file mode 100644 index 000000000..20c39bc94 --- /dev/null +++ b/_codegen/importer_new.go @@ -0,0 +1,5 @@ +// +build go1.9 + +package main + +const SOURCE_IMPORTER = true diff --git a/_codegen/importer_old.go b/_codegen/importer_old.go new file mode 100644 index 000000000..d959f40a9 --- /dev/null +++ b/_codegen/importer_old.go @@ -0,0 +1,5 @@ +// +build !go1.9 + +package main + +const SOURCE_IMPORTER = false diff --git a/_codegen/main.go b/_codegen/main.go index 2e5e8124f..bfdc41a58 100644 --- a/_codegen/main.go +++ b/_codegen/main.go @@ -193,8 +193,15 @@ func parsePackageSource(pkg string) (*types.Scope, *doc.Package, error) { fileList[i] = f } + var imp types.Importer + if SOURCE_IMPORTER { + imp = importer.For("source", nil) + } else { + imp = importer.Default() + } + cfg := types.Config{ - Importer: importer.Default(), + Importer: imp, } info := types.Info{ Defs: make(map[*ast.Ident]types.Object), diff --git a/assert/assertion_format.go b/assert/assertion_format.go index 8a68b608c..6eabf3950 100644 --- a/assert/assertion_format.go +++ b/assert/assertion_format.go @@ -244,6 +244,30 @@ func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url strin return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } +// HasPrefixf asserts that the specified string or list(array, slice...) begins with the +// specified substring or sequence of elements. +// +// assert.HasPrefixf(t, "Hello World", "Hello", "error message %s", "formatted") +// assert.HasPrefixf(t, ["Hello", "there", "World"], ["Hello", "there"], "error message %s", "formatted") +func HasPrefixf(t TestingT, s interface{}, prefix interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HasPrefix(t, s, prefix, append([]interface{}{msg}, args...)...) +} + +// HasSuffixf asserts that the specified string or list(array, slice...) ends with the +// specified substring or sequence of elements. +// +// assert.HasSuffixf(t, "Hello World", "World", "error message %s", "formatted") +// assert.HasSuffixf(t, ["Hello", "there", "World"], ["there", "World"], "error message %s", "formatted") +func HasSuffixf(t TestingT, s interface{}, suffix interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HasSuffix(t, s, suffix, append([]interface{}{msg}, args...)...) +} + // Implementsf asserts that an object is implemented by the specified interface. // // assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) @@ -412,6 +436,22 @@ func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...) } +// NotHasPrefixf asserts the negation of HasPrefix. +func NotHasPrefixf(t TestingT, s interface{}, prefix interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotHasPrefix(t, s, prefix, append([]interface{}{msg}, args...)...) +} + +// NotHasSuffixf asserts the negation of HasSuffix. +func NotHasSuffixf(t TestingT, s interface{}, suffix interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotHasSuffix(t, s, suffix, append([]interface{}{msg}, args...)...) +} + // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") diff --git a/assert/assertion_forward.go b/assert/assertion_forward.go index 3c8012a38..238e4147f 100644 --- a/assert/assertion_forward.go +++ b/assert/assertion_forward.go @@ -477,6 +477,54 @@ func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url s return HTTPSuccessf(a.t, handler, method, url, values, msg, args...) } +// HasPrefix asserts that the specified string or list(array, slice...) begins with the +// specified substring or sequence of elements. +// +// a.HasPrefix("Hello World", "Hello") +// a.HasPrefix(["Hello", "there", "World"], ["Hello", "there"]) +func (a *Assertions) HasPrefix(s interface{}, prefix interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HasPrefix(a.t, s, prefix, msgAndArgs...) +} + +// HasPrefixf asserts that the specified string or list(array, slice...) begins with the +// specified substring or sequence of elements. +// +// a.HasPrefixf("Hello World", "Hello", "error message %s", "formatted") +// a.HasPrefixf(["Hello", "there", "World"], ["Hello", "there"], "error message %s", "formatted") +func (a *Assertions) HasPrefixf(s interface{}, prefix interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HasPrefixf(a.t, s, prefix, msg, args...) +} + +// HasSuffix asserts that the specified string or list(array, slice...) ends with the +// specified substring or sequence of elements. +// +// a.HasSuffix("Hello World", "World") +// a.HasSuffix(["Hello", "there", "World"], ["there", "World"]) +func (a *Assertions) HasSuffix(s interface{}, suffix interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HasSuffix(a.t, s, suffix, msgAndArgs...) +} + +// HasSuffixf asserts that the specified string or list(array, slice...) ends with the +// specified substring or sequence of elements. +// +// a.HasSuffixf("Hello World", "World", "error message %s", "formatted") +// a.HasSuffixf(["Hello", "there", "World"], ["there", "World"], "error message %s", "formatted") +func (a *Assertions) HasSuffixf(s interface{}, suffix interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HasSuffixf(a.t, s, suffix, msg, args...) +} + // Implements asserts that an object is implemented by the specified interface. // // a.Implements((*MyInterface)(nil), new(MyObject)) @@ -813,6 +861,38 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str return NotEqualf(a.t, expected, actual, msg, args...) } +// NotHasPrefix asserts the negation of HasPrefix. +func (a *Assertions) NotHasPrefix(s interface{}, prefix interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotHasPrefix(a.t, s, prefix, msgAndArgs...) +} + +// NotHasPrefixf asserts the negation of HasPrefix. +func (a *Assertions) NotHasPrefixf(s interface{}, prefix interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotHasPrefixf(a.t, s, prefix, msg, args...) +} + +// NotHasSuffix asserts the negation of HasSuffix. +func (a *Assertions) NotHasSuffix(s interface{}, suffix interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotHasSuffix(a.t, s, suffix, msgAndArgs...) +} + +// NotHasSuffixf asserts the negation of HasSuffix. +func (a *Assertions) NotHasSuffixf(s interface{}, suffix interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotHasSuffixf(a.t, s, suffix, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) diff --git a/assert/assertions.go b/assert/assertions.go index eb3b39baf..de401fc3c 100644 --- a/assert/assertions.go +++ b/assert/assertions.go @@ -20,7 +20,7 @@ import ( "github.com/pmezard/go-difflib/difflib" ) -//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl +//go:generate ../codegen -output-package=assert -template=assertion_format.go.tmpl // TestingT is an interface wrapper around *testing.T type TestingT interface { @@ -170,8 +170,8 @@ func isTest(name, prefix string) bool { if len(name) == len(prefix) { // "Test" is ok return true } - rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) - return !unicode.IsLower(rune) + nextRune, _ := utf8.DecodeRuneInString(name[len(prefix):]) + return !unicode.IsLower(nextRune) } func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { @@ -653,12 +653,123 @@ func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{ } +func hasEndings(list, element interface{}) (ok, hasPrefix, hasSuffix bool) { + elementValue := reflect.ValueOf(element) + listValue := reflect.ValueOf(list) + + defer func() { + if e := recover(); e != nil { + ok = false + hasPrefix = false + hasSuffix = false + } + }() + + if reflect.TypeOf(list).Kind() == reflect.String { + ok = true + hasPrefix = strings.HasPrefix(listValue.String(), elementValue.String()) + hasSuffix = strings.HasSuffix(listValue.String(), elementValue.String()) + return + } + + hasPrefix = true + hasSuffix = true + listLen := listValue.Len() + elementLen := elementValue.Len() + for i := 0; i < listLen; i++ { + if i < elementLen { + hasPrefix = hasPrefix && ObjectsAreEqual(listValue.Index(i).Interface(), elementValue.Index(i).Interface()) + } + suffixIndex := elementLen - (listLen - i) + if suffixIndex >= 0 { + hasSuffix = hasSuffix && ObjectsAreEqual(listValue.Index(i).Interface(), elementValue.Index(suffixIndex).Interface()) + } + } + ok = true + return +} + +// HasPrefix asserts that the specified string or list(array, slice...) begins with the +// specified substring or sequence of elements. +// +// assert.HasPrefix(t, "Hello World", "Hello") +// assert.HasPrefix(t, ["Hello", "there", "World"], ["Hello", "there"]) +func HasPrefix(t TestingT, s, prefix interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ok, hasPrefix, _ := hasEndings(s, prefix) + if !ok { + return Fail(t, fmt.Sprintf("%v could not be applied builtin len()", s), msgAndArgs...) + } + if !hasPrefix { + return Fail(t, fmt.Sprintf("%v does not have prefix %v", s, prefix), msgAndArgs...) + } + + return true +} + +// NotHasPrefix asserts the negation of HasPrefix. +func NotHasPrefix(t TestingT, s, prefix interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ok, hasPrefix, _ := hasEndings(s, prefix) + if !ok { + return Fail(t, fmt.Sprintf("%v could not be applied builtin len()", s), msgAndArgs...) + } + if hasPrefix { + return Fail(t, fmt.Sprintf("%v has prefix %v", s, prefix), msgAndArgs...) + } + + return true +} + +// HasSuffix asserts that the specified string or list(array, slice...) ends with the +// specified substring or sequence of elements. +// +// assert.HasSuffix(t, "Hello World", "World") +// assert.HasSuffix(t, ["Hello", "there", "World"], ["there", "World"]) +func HasSuffix(t TestingT, s, suffix interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ok, _, hasSuffix := hasEndings(s, suffix) + if !ok { + return Fail(t, fmt.Sprintf("%v could not be applied builtin len()", s), msgAndArgs...) + } + if !hasSuffix { + return Fail(t, fmt.Sprintf("%v does not have suffix %v", s, suffix), msgAndArgs...) + } + + return true +} + +// NotHasSuffix asserts the negation of HasSuffix. +func NotHasSuffix(t TestingT, s, suffix interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ok, _, hasSuffix := hasEndings(s, suffix) + if !ok { + return Fail(t, fmt.Sprintf("%v could not be applied builtin len()", s), msgAndArgs...) + } + if hasSuffix { + return Fail(t, fmt.Sprintf("%v has suffix %v", s, suffix), msgAndArgs...) + } + + return true +} + // containsElement try loop over the list check if the list includes the element. // return (false, false) if impossible. // return (true, false) if element was not found. // return (true, true) if element was found. func includeElement(list interface{}, element interface{}) (ok, found bool) { - listValue := reflect.ValueOf(list) listKind := reflect.TypeOf(list).Kind() defer func() { @@ -689,7 +800,6 @@ func includeElement(list interface{}, element interface{}) (ok, found bool) { } } return true, false - } // Contains asserts that the specified string, list(array, slice...) or map contains the @@ -712,7 +822,6 @@ func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bo } return true - } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the @@ -735,7 +844,6 @@ func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) } return true - } // Subset asserts that the specified list(array, slice...) contains all diff --git a/assert/assertions_test.go b/assert/assertions_test.go index 332271eb6..dc94e0332 100644 --- a/assert/assertions_test.go +++ b/assert/assertions_test.go @@ -476,8 +476,191 @@ type A struct { Name, Value string } -func TestContains(t *testing.T) { +func TestHasPrefix(t *testing.T) { + mockT := new(testing.T) + list := []string{"Foo", "Bar", "Baz"} + listPrefix := []string{list[0], list[1]} + listSuffix := []string{list[1], list[2]} + + complexList := []*A{ + {"b", "c"}, + {"d", "e"}, + {"g", "h"}, + {"j", "k"}, + } + complexListPrefix := []*A{complexList[0], complexList[1]} + complexListSuffix := []*A{complexList[2], complexList[3]} + + if !HasPrefix(mockT, "", "") { + t.Error("HasPrefix should return true: the empty string is a prefix of the empty string") + } + + if !HasPrefix(mockT, "Hello World", "Hello") { + t.Error("HasPrefix should return true: \"Hello World\" starts with \"Hello\"") + } + if HasPrefix(mockT, "Hello World", "World") { + t.Error("HasPrefix should return false: \"Hello World\" does not start with \"World\"") + } + + if !HasPrefix(mockT, []string{}, []string{}) { + t.Error("HasPrefix should return true: the empty list is a prefix of the empty list") + } + + if !HasPrefix(mockT, list, listPrefix) { + t.Errorf("HasPrefix should return true: %v starts with %v", list, listPrefix) + } + if HasPrefix(mockT, list, listSuffix) { + t.Errorf("HasPrefix should return false: %v does not start with %v", list, listSuffix) + } + + if !HasPrefix(mockT, complexList, complexListPrefix) { + t.Errorf("HasPrefix should return true: %v starts with %v", complexList, complexListPrefix) + } + if HasPrefix(mockT, complexList, complexListSuffix) { + t.Errorf("HasPrefix should return false: %v does not start with %v", complexList, complexListSuffix) + } +} + +func TestNotHasPrefix(t *testing.T) { + mockT := new(testing.T) + + list := []string{"Foo", "Bar", "Baz"} + listPrefix := []string{list[0], list[1]} + listSuffix := []string{list[1], list[2]} + + complexList := []*A{ + {"b", "c"}, + {"d", "e"}, + {"g", "h"}, + {"j", "k"}, + } + complexListPrefix := []*A{complexList[0], complexList[1]} + complexListSuffix := []*A{complexList[2], complexList[3]} + + if NotHasPrefix(mockT, "", "") { + t.Error("NotHasPrefix should return false: the empty string is a prefix of the empty string") + } + + if NotHasPrefix(mockT, "Hello World", "Hello") { + t.Error("NotHasPrefix should return false: \"Hello World\" starts with \"Hello\"") + } + if !NotHasPrefix(mockT, "Hello World", "World") { + t.Error("NotHasPrefix should return true: \"Hello World\" does not start with \"World\"") + } + + if NotHasPrefix(mockT, []string{}, []string{}) { + t.Error("NotHasPrefix should return false: the empty list is a prefix of the empty list") + } + + if NotHasPrefix(mockT, list, listPrefix) { + t.Errorf("NotHasPrefix should return false: %v starts with %v", list, listPrefix) + } + if !NotHasPrefix(mockT, list, listSuffix) { + t.Errorf("NotHasPrefix should return true: %v does not start with %v", list, listSuffix) + } + + if NotHasPrefix(mockT, complexList, complexListPrefix) { + t.Errorf("NotHasPrefix should return false: %v starts with %v", complexList, complexListPrefix) + } + if !NotHasPrefix(mockT, complexList, complexListSuffix) { + t.Errorf("NotHasPrefix should return true: %v does not start with %v", complexList, complexListSuffix) + } +} + +func TestHasSuffix(t *testing.T) { + mockT := new(testing.T) + + list := []string{"Foo", "Bar", "Baz"} + listPrefix := []string{list[0], list[1]} + listSuffix := []string{list[1], list[2]} + + complexList := []*A{ + {"b", "c"}, + {"d", "e"}, + {"g", "h"}, + {"j", "k"}, + } + complexListPrefix := []*A{complexList[0], complexList[1]} + complexListSuffix := []*A{complexList[2], complexList[3]} + + if !HasSuffix(mockT, "", "") { + t.Error("HasSuffix should return true: the empty string is a suffix of the empty string") + } + + if !HasSuffix(mockT, "Hello World", "World") { + t.Error("HasSuffix should return true: \"Hello World\" ends with \"World\"") + } + if HasSuffix(mockT, "Hello World", "Hello") { + t.Error("HasSuffix should return false: \"Hello World\" does not end with \"Hello\"") + } + + if !HasSuffix(mockT, []string{}, []string{}) { + t.Error("HasSuffix should return true: the empty list is a suffix of the empty list") + } + + if !HasSuffix(mockT, list, listSuffix) { + t.Errorf("HasSuffix should return true: %v ends with %v", list, listSuffix) + } + if HasSuffix(mockT, list, listPrefix) { + t.Errorf("HasSuffix should return false: %v does not end with %v", list, listPrefix) + } + + if !HasSuffix(mockT, complexList, complexListSuffix) { + t.Errorf("HasSuffix should return true: %v ends with %v", complexList, complexListSuffix) + } + if HasSuffix(mockT, complexList, complexListPrefix) { + t.Errorf("HasSuffix should return false: %v does not end with %v", complexList, complexListPrefix) + } +} + +func TestNotHasSuffix(t *testing.T) { + mockT := new(testing.T) + + list := []string{"Foo", "Bar", "Baz"} + listPrefix := []string{list[0], list[1]} + listSuffix := []string{list[1], list[2]} + + complexList := []*A{ + {"b", "c"}, + {"d", "e"}, + {"g", "h"}, + {"j", "k"}, + } + complexListPrefix := []*A{complexList[0], complexList[1]} + complexListSuffix := []*A{complexList[2], complexList[3]} + + if NotHasSuffix(mockT, "", "") { + t.Error("NotHasSuffix should return false: the empty string is a suffix of the empty string") + } + + if NotHasSuffix(mockT, "Hello World", "World") { + t.Error("NotHasSuffix should return false: \"Hello World\" ends with \"World\"") + } + if !NotHasSuffix(mockT, "Hello World", "Hello") { + t.Error("NotHasSuffix should return true: \"Hello World\" does not end with \"Hello\"") + } + + if NotHasSuffix(mockT, []string{}, []string{}) { + t.Error("NotHasSuffix should return false: the empty list is a suffix of the empty list") + } + + if NotHasSuffix(mockT, list, listSuffix) { + t.Errorf("NotHasSuffix should return false: %v ends with %v", list, listSuffix) + } + if !NotHasSuffix(mockT, list, listPrefix) { + t.Errorf("NotHasSuffix should return true: %v does not end with %v", list, listPrefix) + } + + if NotHasSuffix(mockT, complexList, complexListSuffix) { + t.Errorf("NotHasSuffix should return false: %v ends with %v", complexList, complexListSuffix) + } + if !NotHasSuffix(mockT, complexList, complexListPrefix) { + t.Errorf("NotHasSuffix should return true: %v does not end with %v", complexList, complexListPrefix) + } +} + +func TestContains(t *testing.T) { mockT := new(testing.T) list := []string{"Foo", "Bar"} complexList := []*A{ @@ -1676,6 +1859,11 @@ func TestComparisonAssertionFunc(t *testing.T) { {"equalValues", t, t, EqualValues}, {"exactly", t, t, Exactly}, {"notEqual", t, nil, NotEqual}, + {"hasPrefix", "abcd", "ab", HasPrefix}, + {"notHasPrefix", "abcd", "bc", NotHasPrefix}, + {"hasSuffix", "abcd", "cd", HasSuffix}, + {"notHasSuffix", "abcd", "bc", NotHasSuffix}, + {"contains", []int{1, 2, 3}, 2, Contains}, {"notContains", []int{1, 2, 3}, 4, NotContains}, {"subset", []int{1, 2, 3, 4}, []int{2, 3}, Subset}, {"notSubset", []int{1, 2, 3, 4}, []int{0, 3}, NotSubset}, diff --git a/assert/forward_assertions.go b/assert/forward_assertions.go index 9ad56851d..a8801db51 100644 --- a/assert/forward_assertions.go +++ b/assert/forward_assertions.go @@ -13,4 +13,4 @@ func New(t TestingT) *Assertions { } } -//go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs +//go:generate ../codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs diff --git a/require/forward_requirements.go b/require/forward_requirements.go index ac71d4058..4c9101f3d 100644 --- a/require/forward_requirements.go +++ b/require/forward_requirements.go @@ -13,4 +13,4 @@ func New(t TestingT) *Assertions { } } -//go:generate go run ../_codegen/main.go -output-package=require -template=require_forward.go.tmpl -include-format-funcs +//go:generate ../codegen -output-package=require -template=require_forward.go.tmpl -include-format-funcs diff --git a/require/require.go b/require/require.go index 5491907f6..8fb7ce2f4 100644 --- a/require/require.go +++ b/require/require.go @@ -604,6 +604,66 @@ func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url strin t.FailNow() } +// HasPrefix asserts that the specified string or list(array, slice...) begins with the +// specified substring or sequence of elements. +// +// assert.HasPrefix(t, "Hello World", "Hello") +// assert.HasPrefix(t, ["Hello", "there", "World"], ["Hello", "there"]) +func HasPrefix(t TestingT, s interface{}, prefix interface{}, msgAndArgs ...interface{}) { + if assert.HasPrefix(t, s, prefix, msgAndArgs...) { + return + } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() +} + +// HasPrefixf asserts that the specified string or list(array, slice...) begins with the +// specified substring or sequence of elements. +// +// assert.HasPrefixf(t, "Hello World", "Hello", "error message %s", "formatted") +// assert.HasPrefixf(t, ["Hello", "there", "World"], ["Hello", "there"], "error message %s", "formatted") +func HasPrefixf(t TestingT, s interface{}, prefix interface{}, msg string, args ...interface{}) { + if assert.HasPrefixf(t, s, prefix, msg, args...) { + return + } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() +} + +// HasSuffix asserts that the specified string or list(array, slice...) ends with the +// specified substring or sequence of elements. +// +// assert.HasSuffix(t, "Hello World", "World") +// assert.HasSuffix(t, ["Hello", "there", "World"], ["there", "World"]) +func HasSuffix(t TestingT, s interface{}, suffix interface{}, msgAndArgs ...interface{}) { + if assert.HasSuffix(t, s, suffix, msgAndArgs...) { + return + } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() +} + +// HasSuffixf asserts that the specified string or list(array, slice...) ends with the +// specified substring or sequence of elements. +// +// assert.HasSuffixf(t, "Hello World", "World", "error message %s", "formatted") +// assert.HasSuffixf(t, ["Hello", "there", "World"], ["there", "World"], "error message %s", "formatted") +func HasSuffixf(t TestingT, s interface{}, suffix interface{}, msg string, args ...interface{}) { + if assert.HasSuffixf(t, s, suffix, msg, args...) { + return + } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() +} + // Implements asserts that an object is implemented by the specified interface. // // assert.Implements(t, (*MyInterface)(nil), new(MyObject)) @@ -1036,6 +1096,50 @@ func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, t.FailNow() } +// NotHasPrefix asserts the negation of HasPrefix. +func NotHasPrefix(t TestingT, s interface{}, prefix interface{}, msgAndArgs ...interface{}) { + if assert.NotHasPrefix(t, s, prefix, msgAndArgs...) { + return + } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() +} + +// NotHasPrefixf asserts the negation of HasPrefix. +func NotHasPrefixf(t TestingT, s interface{}, prefix interface{}, msg string, args ...interface{}) { + if assert.NotHasPrefixf(t, s, prefix, msg, args...) { + return + } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() +} + +// NotHasSuffix asserts the negation of HasSuffix. +func NotHasSuffix(t TestingT, s interface{}, suffix interface{}, msgAndArgs ...interface{}) { + if assert.NotHasSuffix(t, s, suffix, msgAndArgs...) { + return + } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() +} + +// NotHasSuffixf asserts the negation of HasSuffix. +func NotHasSuffixf(t TestingT, s interface{}, suffix interface{}, msg string, args ...interface{}) { + if assert.NotHasSuffixf(t, s, suffix, msg, args...) { + return + } + if h, ok := t.(tHelper); ok { + h.Helper() + } + t.FailNow() +} + // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) diff --git a/require/require_forward.go b/require/require_forward.go index 1637c6c06..10bc37c8d 100644 --- a/require/require_forward.go +++ b/require/require_forward.go @@ -478,6 +478,54 @@ func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url s HTTPSuccessf(a.t, handler, method, url, values, msg, args...) } +// HasPrefix asserts that the specified string or list(array, slice...) begins with the +// specified substring or sequence of elements. +// +// a.HasPrefix("Hello World", "Hello") +// a.HasPrefix(["Hello", "there", "World"], ["Hello", "there"]) +func (a *Assertions) HasPrefix(s interface{}, prefix interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HasPrefix(a.t, s, prefix, msgAndArgs...) +} + +// HasPrefixf asserts that the specified string or list(array, slice...) begins with the +// specified substring or sequence of elements. +// +// a.HasPrefixf("Hello World", "Hello", "error message %s", "formatted") +// a.HasPrefixf(["Hello", "there", "World"], ["Hello", "there"], "error message %s", "formatted") +func (a *Assertions) HasPrefixf(s interface{}, prefix interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HasPrefixf(a.t, s, prefix, msg, args...) +} + +// HasSuffix asserts that the specified string or list(array, slice...) ends with the +// specified substring or sequence of elements. +// +// a.HasSuffix("Hello World", "World") +// a.HasSuffix(["Hello", "there", "World"], ["there", "World"]) +func (a *Assertions) HasSuffix(s interface{}, suffix interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HasSuffix(a.t, s, suffix, msgAndArgs...) +} + +// HasSuffixf asserts that the specified string or list(array, slice...) ends with the +// specified substring or sequence of elements. +// +// a.HasSuffixf("Hello World", "World", "error message %s", "formatted") +// a.HasSuffixf(["Hello", "there", "World"], ["there", "World"], "error message %s", "formatted") +func (a *Assertions) HasSuffixf(s interface{}, suffix interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + HasSuffixf(a.t, s, suffix, msg, args...) +} + // Implements asserts that an object is implemented by the specified interface. // // a.Implements((*MyInterface)(nil), new(MyObject)) @@ -814,6 +862,38 @@ func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg str NotEqualf(a.t, expected, actual, msg, args...) } +// NotHasPrefix asserts the negation of HasPrefix. +func (a *Assertions) NotHasPrefix(s interface{}, prefix interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotHasPrefix(a.t, s, prefix, msgAndArgs...) +} + +// NotHasPrefixf asserts the negation of HasPrefix. +func (a *Assertions) NotHasPrefixf(s interface{}, prefix interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotHasPrefixf(a.t, s, prefix, msg, args...) +} + +// NotHasSuffix asserts the negation of HasSuffix. +func (a *Assertions) NotHasSuffix(s interface{}, suffix interface{}, msgAndArgs ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotHasSuffix(a.t, s, suffix, msgAndArgs...) +} + +// NotHasSuffixf asserts the negation of HasSuffix. +func (a *Assertions) NotHasSuffixf(s interface{}, suffix interface{}, msg string, args ...interface{}) { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + NotHasSuffixf(a.t, s, suffix, msg, args...) +} + // NotNil asserts that the specified object is not nil. // // a.NotNil(err) diff --git a/require/requirements.go b/require/requirements.go index 6b85c5ece..48c502c72 100644 --- a/require/requirements.go +++ b/require/requirements.go @@ -26,4 +26,4 @@ type BoolAssertionFunc func(TestingT, bool, ...interface{}) // for table driven tests. type ErrorAssertionFunc func(TestingT, error, ...interface{}) -//go:generate go run ../_codegen/main.go -output-package=require -template=require.go.tmpl -include-format-funcs +//go:generate ../codegen -output-package=require -template=require.go.tmpl -include-format-funcs diff --git a/suite/suite.go b/suite/suite.go index d708d7d75..17df20fe5 100644 --- a/suite/suite.go +++ b/suite/suite.go @@ -84,7 +84,7 @@ func Run(t *testing.T, suite TestingSuite) { defer failOnPanic(t) suiteSetupDone := false - + methodFinder := reflect.TypeOf(suite) tests := []testing.InternalTest{} for index := 0; index < methodFinder.NumMethod(); index++ { diff --git a/suite/suite_test.go b/suite/suite_test.go index 26dddbd36..e08467d8c 100644 --- a/suite/suite_test.go +++ b/suite/suite_test.go @@ -350,7 +350,7 @@ func TestRunSuite(t *testing.T) { type SuiteSetupSkipTester struct { Suite - setUp bool + setUp bool toreDown bool }