Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assert: NotNil accepts non-nillable types and doesn't fail #570

Open
dnephin opened this issue Mar 7, 2018 · 4 comments
Open

assert: NotNil accepts non-nillable types and doesn't fail #570

dnephin opened this issue Mar 7, 2018 · 4 comments

Comments

@dnephin
Copy link

dnephin commented Mar 7, 2018

func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool {
if h, ok := t.(tHelper); ok {
h.Helper()
}
if !isNil(object) {
return true
}
return Fail(t, "Expected value not to be nil.", msgAndArgs...)
}
// isNil checks if a specified object is nil or not, without Failing.
func isNil(object interface{}) bool {
if object == nil {
return true
}
value := reflect.ValueOf(object)
kind := value.Kind()
if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() {
return true
}

isNil will always return false, so NotNil will always return true for int, string, struct, etc.

I would expect it to error with "invalid type".

@ernesto-jimenez
Copy link
Member

@dnephin that sounds good. Do you want to issue a PR?

@devdinu
Copy link
Contributor

devdinu commented Apr 3, 2018

	type pred func(interface{}) bool
	var x pred
	var ptr *int
	var i interface{}
	var m map[string]string
        var ch chan string

All the above will be nil, it could be a case where the function returns a value and we generally check its not nil. assert.NotNil(t, getSomething()). So all these are valid nil case.

I wouldn't mind adding a log, but failing a test, would make the contract differ.

@dnephin
Copy link
Author

dnephin commented Apr 9, 2018

I wouldn't mind adding a log, but failing a test, would make the contract differ.

@devdinu the contract should be different. This is a bug, not a feature request.

The problem is this:

if kind >= reflect.Chan && kind <= reflect.Slice

If kind is not in that range, isNil returns false, so NotNil assumes it's not nil. However the value can't be nil, so it should be a panic, or a failed test.

Some examples:

	require.NotNil(t, "foo")
	require.NotNil(t, "")
	require.NotNil(t, 0)
	require.NotNil(t, 1)
	require.NotNil(t, mystruct{})

None of these fail the test. This is broken. #584 looks like the correct fix.

@ernesto-jimenez
Copy link
Member

#584 would fail the following test which currently passes.

type something struct{}

func (s something) Error() string {
        return "fail"
}

func foo() error {
        return something{}
}

func TestNotNilWithError(t *testing.T) {
        err := foo()
        NotNil(t, err)
}

If we were to do something like this, we would need something that works with interface types like error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants