testify icon indicating copy to clipboard operation
testify copied to clipboard

Pointers in map keys not treated as equal

Open bioball opened this issue 3 years ago • 5 comments

This assertion fails, when I expect it to succeed:

strOne := "foo"
strTwo := "foo"

assert.Equal(
  t,
  map[*string]string{&strOne: "foo"},
  map[*string]string{&strTwo: "foo"},
)

bioball avatar Jan 07 '22 20:01 bioball

I would try to recreate this error, however the map seems unnecessarily complicated.

strOne := []string{"foo"}[0]
strTwo := []string{"foo"}[0]

assert.Equal(
	t,
	map[*string]string{&strOne: "foo"},
	map[*string]string{&strTwo: "foo"},
)

Makes it easier to read.

OladapoAjala avatar Apr 14 '22 08:04 OladapoAjala

Thanks for the rec; updated the original description

bioball avatar Apr 14 '22 18:04 bioball

@bioball You're welcome, I can confirm that this fails. So the reason it fails is because &strOne and &strTwo are two different pointers.

Try this

  strOne := "foo"
  // strTwo := "foo"
  
  assert.Equal(
  t,
  map[*string]string{&strOne: "foo"},
  map[*string]string{&strOne: "foo"},
  )

The code above passes since you're asserting the equality of the same pointers and the same strings.

image

PS: how do you include code color in your github comment?

OladapoAjala avatar Apr 15 '22 03:04 OladapoAjala

That makes sense. However, I'd expect the test to pass because the docs for assert.Equal states that pointer equality is determined by the equality of their reference values: https://github.com/stretchr/testify/blob/77977386932ab1866a4b9556a7af1ae347531786/assert/assertions.go#L331

I got colors to show up by setting the syntax to go when declaring the code block; e.g.

```go
func GoFunc() {
}
```

bioball avatar Apr 15 '22 22:04 bioball

Thanks for pointing this out. I took sometime to think about this problem and the only logical conclusion I have is that you're using pointers as keys in a map. Hence, the pointers actual values .i.e the addresses are used as the keys as opposed to the value the pointer points to.

Take this case for example:

  strOne := "dapo"
  strTwo := "dapo"
  mapOne := map[string]*string{"foo": &strOne}
  mapTwo := map[string]*string{"foo": &strTwo}

The keys are strings but the values are pointers and the test passes.

OladapoAjala avatar Apr 16 '22 23:04 OladapoAjala

I'm glad this works as it.

dolmen avatar Jul 25 '23 05:07 dolmen