stretchr / testify

A toolkit with common assertions and mocks that plays nicely with the standard library
MIT License
23.15k stars 1.59k forks source link

assert fails and expects to dereference a reference #1551

Closed Anacardo89 closed 7 months ago

Anacardo89 commented 7 months ago

This happens consistently in the code i'm about to provide, it's a linked list implementation. This issue is not reproduced in the std library.

Description

i have a prepend and an insert implementation, which in fact just calls prepend for the first 2 iterations: i test prepend adding 3 values to the list and it grabs all the values just fine, when i test the insert however it says it expects a dereference to a reference, which i believe is the thing itself so it should just pass the test? 1 - Any value added after the first will fail with this same expectation, but the first value can be asserted correctly with no problems. 2 - the values that cannot be asserted correctly do pass if asserted against the dereference of the type 3 - in the std library behaviour is consistent in which calls to insert will always be asserted correctly

Step To Reproduce

insert + tests:

func (l *DLL) InsertNodeAt(idx int, n *Node) error {
    if idx > l.length {
        return ErrOutOfBounds
    }
    if l.length == 0 {
        l.PrependNode(n)
        return nil
    }
    switch idx {
    case 0:
        l.PrependNode(n)
        return nil
    case l.length:
        l.AppendNode(n)
        return nil
    }
    current, prev := l.head, l.head
    for i := 0; i < idx; i++ {
        prev = current
        current = current.next
    }
    n.next, n.prev = current, prev
    prev.next, current.prev = n, n
    l.length++
    return nil
}

func TestDllInsertNodeAt(t *testing.T) {
    l := New()
    n := &Node{val: 10}
    t.Run("InsertAt() - Err: out of bounds", func(t *testing.T) {
        err := l.InsertNodeAt(5, n)
        assert.Equal(t, err, ErrOutOfBounds)
    })
    n = &Node{val: 10}
    t.Run("InsertAt() - Length 0", func(t *testing.T) {
        _ = l.InsertNodeAt(0, n)
        assert.Equal(t, l.head.val, 10)
    })
    n = &Node{val: 20}
    t.Run("InsertAt() - Index 0", func(t *testing.T) {
        _ = l.InsertAt(0, n)
        assert.Equal(t, l.head.val, 20)
        assert.Equal(t, l.head.next.val, 10)
        assert.Equal(t, l.head.next.prev.val, &Node{val: 20})
    })
}

Prepend + tests:

func (l *DLL) PrependNode(n *Node) {
    if l.length == 0 {
        l.head, l.tail = n, n
    } else {
        n.next = l.head
        l.head.prev = n
        l.head = n
    }
    l.length++
}

func TestDllPrependNode(t *testing.T) {
    l := New()
    n := &Node{val: 21}
    t.Run("Prepend()  - Length 0", func(t *testing.T) {
        l.PrependNode(n)
        assert.Equal(t, l.head.val, 21)
    })
    n = &Node{val: 35}
    t.Run("Prepend() - Length 1", func(t *testing.T) {
        l.PrependNode(n)
        assert.Equal(t, l.head.val, 35)
        assert.Equal(t, l.head.next.val, 21)
    })
    n = &Node{val: 15}
    t.Run("Prepend() - Length > 1", func(t *testing.T) {
        l.PrependNode(n)
        assert.Equal(t, l.head.val, 15)
        assert.Equal(t, l.head.next.val, 35)
    })
}

std library

func TestDllInsertNodeAt2(t *testing.T) {
    l := New()
    n := &Node{val: 10}
    _ = l.InsertNodeAt(0, n)
    if l.head.val != 10 {
        t.Fail()
    }
    n = &Node{val: 20}
    _ = l.InsertNodeAt(0, n)
    if l.head.val != 20 {
        t.Fail()
    }
    n = &Node{val: 30}
    _ = l.InsertNodeAt(1, n)
    if l.head.next.val != 30 {
        t.Fail()
    }
}

The structs in question so you can fully reproduce it:

type Node struct {
    next *Node
    prev *Node
    val  interface{}
}

type DLL struct {
    length int
    head   *Node
    tail   *Node
}

Expected behavior

Tl;Dr: tests not passing because of weird type magic same tests pass in std library tests should also pass without need for weird type magic

Actual behavior

--- FAIL: TestDllInsertNodeAt (0.00s)
    --- FAIL: TestDllInsertNodeAt/InsertAt()_-_Index_0 (0.00s)
        /home/anacardo/go/src/ds/lists/dll/nodeOps_test.go:85: 
                Error Trace:    /home/anacardo/go/src/ds/lists/dll/nodeOps_test.go:85
                Error:          Not equal: 
                                expected: *dll.Node(&dll.Node{next:(*dll.Node)(nil), prev:(*dll.Node)(nil), val:20})
                                actual  : int(20)
                Test:           TestDllInsertNodeAt/InsertAt()_-_Index_0
FAIL
FAIL    github.com/Anacardo89/ds/lists/dll  0.003s
FAIL
Anacardo89 commented 7 months ago

Nevermind, i just realized i was calling a different function. Typical, you spend 3 hours looking for something and realize the mistake immediately after you post it so the internet can see it in all its glory. Be like me folks.