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

NotSame should fail if args are not pointers #1661 #1664

Merged
merged 11 commits into from
Oct 28, 2024
30 changes: 22 additions & 8 deletions assert/assertions.go
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,13 @@ func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) b
h.Helper()
}

if !samePointers(expected, actual) {
same, ok := samePointers(expected, actual)
if !ok {
return Fail(t, "Both arguments must be pointers", msgAndArgs...)
}

if !same {
// both are pointers but not the same type & pointing to the same address
return Fail(t, fmt.Sprintf("Not same: \n"+
"expected: %p %#v\n"+
"actual : %p %#v", expected, expected, actual, actual), msgAndArgs...)
Expand All @@ -522,29 +528,37 @@ func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}
h.Helper()
}

if samePointers(expected, actual) {
same, ok := samePointers(expected, actual)
if !ok {
//fails when the arguments are not pointers
return !(Fail(t, "Both arguments must be pointers", msgAndArgs...))
}

if same {
return Fail(t, fmt.Sprintf(
"Expected and actual point to the same object: %p %#v",
expected, expected), msgAndArgs...)
}
return true
}

// samePointers compares two generic interface objects and returns whether
// they point to the same object
func samePointers(first, second interface{}) bool {
// samePointers checks if two generic interface objects are pointers to
// the same object. It returns two values: a boolean indicating if they
// point to the same object, and another boolean indicating whether both
// inputs are valid pointers of the same type.
func samePointers(first, second interface{}) (same bool, ok bool) {
sikehish marked this conversation as resolved.
Show resolved Hide resolved
firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second)
if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr {
return false
return false, false //not both are pointers
}

firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second)
if firstType != secondType {
return false
return false, true // both are pointers, but of different types
}

// compare pointer addresses
return first == second
return first == second, true
}

// formatUnequalValues takes two values of arbitrary types and returns string
Expand Down
58 changes: 39 additions & 19 deletions assert/assertions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,39 +605,59 @@ func Test_samePointers(t *testing.T) {
second interface{}
}
tests := []struct {
name string
args args
assertion BoolAssertionFunc
name string
args args
same BoolAssertionFunc
ok BoolAssertionFunc
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's perfect. 👌

Can you add a couple more test cases for when the left and right arguments aren't pointers but the other one is, like:

  • args{first: 1, second: p}
  • args{first: p, second: 1}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, I've added 2 additional test cases now

}{
{
name: "1 != 2",
args: args{first: 1, second: 2},
assertion: False,
name: "1 != 2",
args: args{first: 1, second: 2},
same: False,
ok: False,
},
{
name: "1 != 1 (not same ptr)",
args: args{first: 1, second: 1},
same: False,
ok: False,
},
{
name: "ptr(1) == ptr(1)",
args: args{first: p, second: p},
same: True,
ok: True,
},
{
name: "1 != 1 (not same ptr)",
args: args{first: 1, second: 1},
assertion: False,
name: "int(1) != float32(1)",
args: args{first: int(1), second: float32(1)},
same: False,
ok: False,
},
{
name: "ptr(1) == ptr(1)",
args: args{first: p, second: p},
assertion: True,
name: "array != slice",
args: args{first: [2]int{1, 2}, second: []int{1, 2}},
same: False,
ok: False,
},
{
name: "int(1) != float32(1)",
args: args{first: int(1), second: float32(1)},
assertion: False,
name: "non-pointer vs pointer (1 != ptr(2))",
args: args{first: 1, second: p},
same: False,
ok: False,
},
{
name: "array != slice",
args: args{first: [2]int{1, 2}, second: []int{1, 2}},
assertion: False,
name: "pointer vs non-pointer (ptr(2) != 1)",
args: args{first: p, second: 1},
same: False,
ok: False,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.assertion(t, samePointers(tt.args.first, tt.args.second))
same, ok := samePointers(tt.args.first, tt.args.second)
tt.same(t, same)
tt.ok(t, ok)
})
}
}
Expand Down