A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/stretchr/testify/issues/1524 below:

guard or support comparing with untyped nil · Issue #1524 · stretchr/testify · GitHub

Hi!

The using of ObjectsAreEqual-based functions with untyped nil doesn't make sense for any non-interface types, because of expected and actual are interfaces:

func ObjectsAreEqual(expected, actual interface{}) bool {
	if expected == nil || actual == nil {
		return expected == actual   // You cannot do this, because 
		                            // expected and actual are interfaces
	}

As a consequence, Equal, EqualValues and Exactly will always fail:

    fmt.Println(assert.Equal(t, nil, nilChan))          // false
    fmt.Println(assert.Equal(t, nil, nilFunc))          // false, cannot take func type as argument
    fmt.Println(assert.Equal(t, nil, nilInterface))     // true   !
    fmt.Println(assert.Equal(t, nil, nilMap))           // false
    fmt.Println(assert.Equal(t, nil, nilPointer))       // false
    fmt.Println(assert.Equal(t, nil, nilSlice))         // false
    fmt.Println(assert.Equal(t, nil, nilUnsafePointer)) // false

    fmt.Println(assert.EqualValues(t, nil, nilChan))          // false
    fmt.Println(assert.EqualValues(t, nil, nilFunc))          // false
    fmt.Println(assert.EqualValues(t, nil, nilInterface))     // true   !
    fmt.Println(assert.EqualValues(t, nil, nilMap))           // false
    fmt.Println(assert.EqualValues(t, nil, nilPointer))       // false
    fmt.Println(assert.EqualValues(t, nil, nilSlice))         // false
    fmt.Println(assert.EqualValues(t, nil, nilUnsafePointer)) // false

    fmt.Println(assert.Exactly(t, nil, nilChan))          // false, Types expected to match exactly
    fmt.Println(assert.Exactly(t, nil, nilFunc))          // false, Types expected to match exactly
    fmt.Println(assert.Exactly(t, nil, nilInterface))     // true   !
    fmt.Println(assert.Exactly(t, nil, nilMap))           // false, Types expected to match exactly
    fmt.Println(assert.Exactly(t, nil, nilPointer))       // false, Types expected to match exactly
    fmt.Println(assert.Exactly(t, nil, nilSlice))         // false, Types expected to match exactly
    fmt.Println(assert.Exactly(t, nil, nilUnsafePointer)) // false, Types expected to match exactly

And NotEqual and NotEqualValues will always pass:

    fmt.Println(assert.NotEqual(t, nil, nilChan))          // true
    fmt.Println(assert.NotEqual(t, nil, nilFunc))          // false, cannot take func type as argument
    fmt.Println(assert.NotEqual(t, nil, nilInterface))     // false  !
    fmt.Println(assert.NotEqual(t, nil, nilMap))           // true
    fmt.Println(assert.NotEqual(t, nil, nilPointer))       // true
    fmt.Println(assert.NotEqual(t, nil, nilSlice))         // true
    fmt.Println(assert.NotEqual(t, nil, nilUnsafePointer)) // true

    fmt.Println(assert.NotEqualValues(t, nil, nilChan))          // true
    fmt.Println(assert.NotEqualValues(t, nil, nilFunc))          // true
    fmt.Println(assert.NotEqualValues(t, nil, nilInterface))     // false  !
    fmt.Println(assert.NotEqualValues(t, nil, nilMap))           // true
    fmt.Println(assert.NotEqualValues(t, nil, nilPointer))       // true
    fmt.Println(assert.NotEqualValues(t, nil, nilSlice))         // true
    fmt.Println(assert.NotEqualValues(t, nil, nilUnsafePointer)) // true

The right way is to use typed nil:

    fmt.Println(assert.Equal(t, (chan struct{})(nil), nilChan))           // true
    fmt.Println(assert.Equal(t, (func())(nil), nilFunc))                  // false, cannot take func type as argument
    fmt.Println(assert.Equal(t, (map[int]int)(nil), nilMap))              // true
    fmt.Println(assert.Equal(t, (*int)(nil), nilPointer))                 // true
    fmt.Println(assert.Equal(t, []int(nil), nilSlice))                    // true
    fmt.Println(assert.Equal(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // true

    fmt.Println(assert.EqualValues(t, (chan struct{})(nil), nilChan))           // true
    fmt.Println(assert.EqualValues(t, (func())(nil), nilFunc))                  // true
    fmt.Println(assert.EqualValues(t, (map[int]int)(nil), nilMap))              // true
    fmt.Println(assert.EqualValues(t, (*int)(nil), nilPointer))                 // true
    fmt.Println(assert.EqualValues(t, []int(nil), nilSlice))                    // true
    fmt.Println(assert.EqualValues(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // true
    
    fmt.Println(assert.Exactly(t, (chan struct{})(nil), nilChan))           // true
    fmt.Println(assert.Exactly(t, (func())(nil), nilFunc))                  // false, cannot take func type as argument
    fmt.Println(assert.Exactly(t, (map[int]int)(nil), nilMap))              // true
    fmt.Println(assert.Exactly(t, (*int)(nil), nilPointer))                 // true
    fmt.Println(assert.Exactly(t, []int(nil), nilSlice))                    // true
    fmt.Println(assert.Exactly(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // true

    fmt.Println(assert.NotEqual(t, (chan struct{})(nil), nilChan))           // false
    fmt.Println(assert.NotEqual(t, (func())(nil), nilFunc))                  // false, cannot take func type as argument
    fmt.Println(assert.NotEqual(t, (map[int]int)(nil), nilMap))              // false
    fmt.Println(assert.NotEqual(t, (*int)(nil), nilPointer))                 // false
    fmt.Println(assert.NotEqual(t, []int(nil), nilSlice))                    // false
    fmt.Println(assert.NotEqual(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // false

    fmt.Println(assert.NotEqualValues(t, (chan struct{})(nil), nilChan))           // false
    fmt.Println(assert.NotEqualValues(t, (func())(nil), nilFunc))                  // false
    fmt.Println(assert.NotEqualValues(t, (map[int]int)(nil), nilMap))              // false
    fmt.Println(assert.NotEqualValues(t, (*int)(nil), nilPointer))                 // false
    fmt.Println(assert.NotEqualValues(t, []int(nil), nilSlice))                    // false
    fmt.Println(assert.NotEqualValues(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // false

But this is verbose and we also see inconsistency of functions when working with nilFunc.

Better to just use Nil/NotNil:

    fmt.Println(nilChan == nil)          // true
    fmt.Println(nilFunc == nil)          // true
    fmt.Println(nilInterface == nil)     // true
    fmt.Println(nilMap == nil)           // true
    fmt.Println(nilPointer == nil)       // true
    fmt.Println(nilSlice == nil)         // true
    fmt.Println(nilUnsafePointer == nil) // true

    fmt.Println(assert.Nil(t, nilChan))          // true
    fmt.Println(assert.Nil(t, nilFunc))          // true
    fmt.Println(assert.Nil(t, nilInterface))     // true
    fmt.Println(assert.Nil(t, nilMap))           // true
    fmt.Println(assert.Nil(t, nilPointer))       // true
    fmt.Println(assert.Nil(t, nilSlice))         // true
    fmt.Println(assert.Nil(t, nilUnsafePointer)) // true

    fmt.Println(assert.NotNil(t, nilChan))          // false
    fmt.Println(assert.NotNil(t, nilFunc))          // false
    fmt.Println(assert.NotNil(t, nilInterface))     // false
    fmt.Println(assert.NotNil(t, nilMap))           // false
    fmt.Println(assert.NotNil(t, nilPointer))       // false
    fmt.Println(assert.NotNil(t, nilSlice))         // false
    fmt.Println(assert.NotNil(t, nilUnsafePointer)) // false

Full snippet:
https://go.dev/play/p/ClGstUJWkYB

package main

import (
	"fmt"
	"testing"
	"unsafe"

	"github.com/stretchr/testify/assert"
)

func Test(t *testing.T) {
	var (
		nilChan          chan struct{}
		nilFunc          func()
		nilInterface     any
		nilMap           map[int]int
		nilPointer       *int
		nilSlice         []int
		nilUnsafePointer unsafe.Pointer
	)

	fmt.Println("\nEqual")
	fmt.Println(assert.Equal(t, nil, nilChan))          // false
	fmt.Println(assert.Equal(t, nil, nilFunc))          // false, cannot take func type as argument
	fmt.Println(assert.Equal(t, nil, nilInterface))     // true   !
	fmt.Println(assert.Equal(t, nil, nilMap))           // false
	fmt.Println(assert.Equal(t, nil, nilPointer))       // false
	fmt.Println(assert.Equal(t, nil, nilSlice))         // false
	fmt.Println(assert.Equal(t, nil, nilUnsafePointer)) // false

	fmt.Println("\nEqualValues")
	fmt.Println(assert.EqualValues(t, nil, nilChan))          // false
	fmt.Println(assert.EqualValues(t, nil, nilFunc))          // false
	fmt.Println(assert.EqualValues(t, nil, nilInterface))     // true   !
	fmt.Println(assert.EqualValues(t, nil, nilMap))           // false
	fmt.Println(assert.EqualValues(t, nil, nilPointer))       // false
	fmt.Println(assert.EqualValues(t, nil, nilSlice))         // false
	fmt.Println(assert.EqualValues(t, nil, nilUnsafePointer)) // false

	fmt.Println("\nExactly")
	fmt.Println(assert.Exactly(t, nil, nilChan))          // false, Types expected to match exactly
	fmt.Println(assert.Exactly(t, nil, nilFunc))          // false, Types expected to match exactly
	fmt.Println(assert.Exactly(t, nil, nilInterface))     // true   !
	fmt.Println(assert.Exactly(t, nil, nilMap))           // false, Types expected to match exactly
	fmt.Println(assert.Exactly(t, nil, nilPointer))       // false, Types expected to match exactly
	fmt.Println(assert.Exactly(t, nil, nilSlice))         // false, Types expected to match exactly
	fmt.Println(assert.Exactly(t, nil, nilUnsafePointer)) // false, Types expected to match exactly

	fmt.Println("\nNotEqual")
	fmt.Println(assert.NotEqual(t, nil, nilChan))          // true
	fmt.Println(assert.NotEqual(t, nil, nilFunc))          // false, cannot take func type as argument
	fmt.Println(assert.NotEqual(t, nil, nilInterface))     // false  !
	fmt.Println(assert.NotEqual(t, nil, nilMap))           // true
	fmt.Println(assert.NotEqual(t, nil, nilPointer))       // true
	fmt.Println(assert.NotEqual(t, nil, nilSlice))         // true
	fmt.Println(assert.NotEqual(t, nil, nilUnsafePointer)) // true

	fmt.Println("\nNotEqualValues")
	fmt.Println(assert.NotEqualValues(t, nil, nilChan))          // true
	fmt.Println(assert.NotEqualValues(t, nil, nilFunc))          // true
	fmt.Println(assert.NotEqualValues(t, nil, nilInterface))     // false  !
	fmt.Println(assert.NotEqualValues(t, nil, nilMap))           // true
	fmt.Println(assert.NotEqualValues(t, nil, nilPointer))       // true
	fmt.Println(assert.NotEqualValues(t, nil, nilSlice))         // true
	fmt.Println(assert.NotEqualValues(t, nil, nilUnsafePointer)) // true

	// ------------------------------------------------------------------------------------------

	fmt.Println("\nEqual with typed nil")
	fmt.Println(assert.Equal(t, (chan struct{})(nil), nilChan))           // true
	fmt.Println(assert.Equal(t, (func())(nil), nilFunc))                  // false, cannot take func type as argument
	fmt.Println(assert.Equal(t, (map[int]int)(nil), nilMap))              // true
	fmt.Println(assert.Equal(t, (*int)(nil), nilPointer))                 // true
	fmt.Println(assert.Equal(t, []int(nil), nilSlice))                    // true
	fmt.Println(assert.Equal(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // true

	fmt.Println("\nEqualValues with typed nil")
	fmt.Println(assert.EqualValues(t, (chan struct{})(nil), nilChan))           // true
	fmt.Println(assert.EqualValues(t, (func())(nil), nilFunc))                  // true
	fmt.Println(assert.EqualValues(t, (map[int]int)(nil), nilMap))              // true
	fmt.Println(assert.EqualValues(t, (*int)(nil), nilPointer))                 // true
	fmt.Println(assert.EqualValues(t, []int(nil), nilSlice))                    // true
	fmt.Println(assert.EqualValues(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // true

	fmt.Println("\nExactly with typed nil")
	fmt.Println(assert.Exactly(t, (chan struct{})(nil), nilChan))           // true
	fmt.Println(assert.Exactly(t, (func())(nil), nilFunc))                  // false, cannot take func type as argument
	fmt.Println(assert.Exactly(t, (map[int]int)(nil), nilMap))              // true
	fmt.Println(assert.Exactly(t, (*int)(nil), nilPointer))                 // true
	fmt.Println(assert.Exactly(t, []int(nil), nilSlice))                    // true
	fmt.Println(assert.Exactly(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // true

	fmt.Println("\nNotEqual with typed nil")
	fmt.Println(assert.NotEqual(t, (chan struct{})(nil), nilChan))           // false
	fmt.Println(assert.NotEqual(t, (func())(nil), nilFunc))                  // false, cannot take func type as argument
	fmt.Println(assert.NotEqual(t, (map[int]int)(nil), nilMap))              // false
	fmt.Println(assert.NotEqual(t, (*int)(nil), nilPointer))                 // false
	fmt.Println(assert.NotEqual(t, []int(nil), nilSlice))                    // false
	fmt.Println(assert.NotEqual(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // false

	fmt.Println("\nNotEqualValues with typed nil")
	fmt.Println(assert.NotEqualValues(t, (chan struct{})(nil), nilChan))           // false
	fmt.Println(assert.NotEqualValues(t, (func())(nil), nilFunc))                  // false
	fmt.Println(assert.NotEqualValues(t, (map[int]int)(nil), nilMap))              // false
	fmt.Println(assert.NotEqualValues(t, (*int)(nil), nilPointer))                 // false
	fmt.Println(assert.NotEqualValues(t, []int(nil), nilSlice))                    // false
	fmt.Println(assert.NotEqualValues(t, (unsafe.Pointer)(nil), nilUnsafePointer)) // false

	// ------------------------------------------------------------------------------------------

	fmt.Println("\nGO ==")
	fmt.Println(nilChan == nil)          // true
	fmt.Println(nilFunc == nil)          // true
	fmt.Println(nilInterface == nil)     // true
	fmt.Println(nilMap == nil)           // true
	fmt.Println(nilPointer == nil)       // true
	fmt.Println(nilSlice == nil)         // true
	fmt.Println(nilUnsafePointer == nil) // true

	fmt.Println("\nNil")
	fmt.Println(assert.Nil(t, nilChan))          // true
	fmt.Println(assert.Nil(t, nilFunc))          // true
	fmt.Println(assert.Nil(t, nilInterface))     // true
	fmt.Println(assert.Nil(t, nilMap))           // true
	fmt.Println(assert.Nil(t, nilPointer))       // true
	fmt.Println(assert.Nil(t, nilSlice))         // true
	fmt.Println(assert.Nil(t, nilUnsafePointer)) // true

	fmt.Println("\nNotNil")
	fmt.Println(assert.NotNil(t, nilChan))          // false
	fmt.Println(assert.NotNil(t, nilFunc))          // false
	fmt.Println(assert.NotNil(t, nilInterface))     // false
	fmt.Println(assert.NotNil(t, nilMap))           // false
	fmt.Println(assert.NotNil(t, nilPointer))       // false
	fmt.Println(assert.NotNil(t, nilSlice))         // false
	fmt.Println(assert.NotNil(t, nilUnsafePointer)) // false
}

Example of bug/typo in testify:

assert.NotEqual(t, nil, call.WaitFor)

(call.WaitFor is (<-chan time.Time)(nil)).

Covered by testifylint#nil-compare.


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4