Skip to content

Commit

Permalink
Implement prefix and suffix assertions
Browse files Browse the repository at this point in the history
  • Loading branch information
georgelesica-wf committed May 2, 2019
1 parent 34c6fa2 commit f52b7e8
Show file tree
Hide file tree
Showing 16 changed files with 638 additions and 14 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
*.a
*.so

# Binaries
codegen

# Folders
_obj
_test
Expand Down
4 changes: 4 additions & 0 deletions .travis.gogenerate.sh
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
5 changes: 5 additions & 0 deletions _codegen/importer_new.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// +build go1.9

package main

const SOURCE_IMPORTER = true
5 changes: 5 additions & 0 deletions _codegen/importer_old.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// +build !go1.9

package main

const SOURCE_IMPORTER = false
9 changes: 8 additions & 1 deletion _codegen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
40 changes: 40 additions & 0 deletions assert/assertion_format.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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")
Expand Down
80 changes: 80 additions & 0 deletions assert/assertion_forward.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)
Expand Down
122 changes: 115 additions & 7 deletions assert/assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
Loading

0 comments on commit f52b7e8

Please sign in to comment.