-
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(Between): handles value implementing Compare & Less methods
as well as Gt, Gte, Lt and Lte of course. Compare and/or Less methods signatures follow: func (a T) Less(b T) bool // returns true if a < b func (a T) Compare(b T) int // returns -1 if a < b, 1 if a > b, 0 if a == b Additional Between, Gt, Gte, Lt and Lte changes: - failure reports display numbers as elsewhere; - docs fixed. Signed-off-by: Maxime Soulé <[email protected]>
- Loading branch information
Showing
7 changed files
with
519 additions
and
107 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// Copyright (c) 2021-2022, Maxime Soulé | ||
// All rights reserved. | ||
// | ||
// This source code is licensed under the BSD-style license found in the | ||
// LICENSE file in the root directory of this source tree. | ||
|
||
package types | ||
|
||
import ( | ||
"reflect" | ||
|
||
"github.com/maxatome/go-testdeep/internal/dark" | ||
) | ||
|
||
// NewOrder returns a function able to compare 2 non-nil values of type "t". | ||
// It returns nil if the type "t" is not comparable. | ||
func NewOrder(t reflect.Type) func(a, b reflect.Value) int { | ||
// Compare(T) int | ||
if m, ok := cmpMethod("Compare", t, Int); ok { | ||
return func(va, vb reflect.Value) int { | ||
// use dark.MustGetInterface() to bypass possible private fields | ||
ret := m.Call([]reflect.Value{ | ||
reflect.ValueOf(dark.MustGetInterface(va)), | ||
reflect.ValueOf(dark.MustGetInterface(vb)), | ||
}) | ||
return int(ret[0].Int()) | ||
} | ||
} | ||
|
||
// Less(T) bool | ||
if m, ok := cmpMethod("Less", t, Bool); ok { | ||
return func(va, vb reflect.Value) int { | ||
// use dark.MustGetInterface() to bypass possible private fields | ||
va = reflect.ValueOf(dark.MustGetInterface(va)) | ||
vb = reflect.ValueOf(dark.MustGetInterface(vb)) | ||
ret := m.Call([]reflect.Value{va, vb}) | ||
if ret[0].Bool() { // a < b | ||
return -1 | ||
} | ||
ret = m.Call([]reflect.Value{vb, va}) | ||
if ret[0].Bool() { // b < a | ||
return 1 | ||
} | ||
return 0 | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func cmpMethod(name string, in, out reflect.Type) (reflect.Value, bool) { | ||
if equal, ok := in.MethodByName(name); ok { | ||
ft := equal.Type | ||
if !ft.IsVariadic() && | ||
ft.NumIn() == 2 && | ||
ft.NumOut() == 1 && | ||
ft.In(0) == in && | ||
ft.In(1) == in && | ||
ft.Out(0) == out { | ||
return equal.Func, true | ||
} | ||
} | ||
return reflect.Value{}, false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// Copyright (c) 2022, Maxime Soulé | ||
// All rights reserved. | ||
// | ||
// This source code is licensed under the BSD-style license found in the | ||
// LICENSE file in the root directory of this source tree. | ||
|
||
package types_test | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
"github.com/maxatome/go-testdeep/internal/test" | ||
"github.com/maxatome/go-testdeep/internal/types" | ||
) | ||
|
||
type compareType int | ||
|
||
func (i compareType) Compare(j compareType) int { | ||
if i < j { | ||
return -1 | ||
} | ||
if i > j { | ||
return 1 | ||
} | ||
return 0 | ||
} | ||
|
||
type lessType int | ||
|
||
func (i lessType) Less(j lessType) bool { | ||
return i < j | ||
} | ||
|
||
type badType1 int | ||
|
||
func (i badType1) Compare(j ...badType1) int { return 0 } // IsVariadic() | ||
func (i badType1) Less(j, k badType1) bool { return false } // NumIn() == 3 | ||
|
||
type badType2 int | ||
|
||
func (i badType2) Compare() int { return 0 } // NumIn() == 1 | ||
func (i badType2) Less(j badType2) {} // NumOut() == 0 | ||
|
||
type badType3 int | ||
|
||
func (i badType3) Compare(j badType3) (int, int) { return 0, 0 } // NumOut() == 2 | ||
func (i badType3) Less(j int) bool { return false } // In(1) ≠ in | ||
|
||
type badType4 int | ||
|
||
func (i badType4) Compare(j badType4) bool { return false } // Out(0) ≠ out | ||
func (i badType4) Less(j badType4) int { return 0 } // Out(0) ≠ out | ||
|
||
func TestOrder(t *testing.T) { | ||
if types.NewOrder(reflect.TypeOf(0)) != nil { | ||
t.Error("types.NewOrder(int) returned non-nil func") | ||
} | ||
|
||
fn := types.NewOrder(reflect.TypeOf(compareType(0))) | ||
if fn == nil { | ||
t.Error("types.NewOrder(compareType) returned nil func") | ||
} else { | ||
a, b := reflect.ValueOf(compareType(1)), reflect.ValueOf(compareType(2)) | ||
test.EqualInt(t, fn(a, b), -1) | ||
test.EqualInt(t, fn(b, a), 1) | ||
test.EqualInt(t, fn(a, a), 0) | ||
} | ||
|
||
fn = types.NewOrder(reflect.TypeOf(lessType(0))) | ||
if fn == nil { | ||
t.Error("types.NewOrder(lessType) returned nil func") | ||
} else { | ||
a, b := reflect.ValueOf(lessType(1)), reflect.ValueOf(lessType(2)) | ||
test.EqualInt(t, fn(a, b), -1) | ||
test.EqualInt(t, fn(b, a), 1) | ||
test.EqualInt(t, fn(a, a), 0) | ||
} | ||
|
||
if types.NewOrder(reflect.TypeOf(badType1(0))) != nil { | ||
t.Error("types.NewOrder(badType1) returned non-nil func") | ||
} | ||
if types.NewOrder(reflect.TypeOf(badType2(0))) != nil { | ||
t.Error("types.NewOrder(badType2) returned non-nil func") | ||
} | ||
if types.NewOrder(reflect.TypeOf(badType3(0))) != nil { | ||
t.Error("types.NewOrder(badType3) returned non-nil func") | ||
} | ||
if types.NewOrder(reflect.TypeOf(badType4(0))) != nil { | ||
t.Error("types.NewOrder(badType4) returned non-nil func") | ||
} | ||
} |
Oops, something went wrong.