Skip to content

Commit e181204

Browse files
committed
feat: add Sort and Sorted operators
Signed-off-by: Maxime Soulé <[email protected]>
1 parent a0916b3 commit e181204

11 files changed

+1086
-2
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ See [FAQ](https://go-testdeep.zetta.rocks/faq/).
342342
[`Shallow`]: https://go-testdeep.zetta.rocks/operators/shallow/
343343
[`Slice`]: https://go-testdeep.zetta.rocks/operators/slice/
344344
[`Smuggle`]: https://go-testdeep.zetta.rocks/operators/smuggle/
345+
[`Sort`]: https://go-testdeep.zetta.rocks/operators/sort/
346+
[`Sorted`]: https://go-testdeep.zetta.rocks/operators/sorted/
345347
[`SStruct`]: https://go-testdeep.zetta.rocks/operators/sstruct/
346348
[`String`]: https://go-testdeep.zetta.rocks/operators/string/
347349
[`Struct`]: https://go-testdeep.zetta.rocks/operators/struct/
@@ -407,6 +409,8 @@ See [FAQ](https://go-testdeep.zetta.rocks/faq/).
407409
[`CmpShallow`]: https://go-testdeep.zetta.rocks/operators/shallow/#cmpshallow-shortcut
408410
[`CmpSlice`]: https://go-testdeep.zetta.rocks/operators/slice/#cmpslice-shortcut
409411
[`CmpSmuggle`]: https://go-testdeep.zetta.rocks/operators/smuggle/#cmpsmuggle-shortcut
412+
[`CmpSort`]: https://go-testdeep.zetta.rocks/operators/sort/#cmpsort-shortcut
413+
[`CmpSorted`]: https://go-testdeep.zetta.rocks/operators/sorted/#cmpsorted-shortcut
410414
[`CmpSStruct`]: https://go-testdeep.zetta.rocks/operators/sstruct/#cmpsstruct-shortcut
411415
[`CmpString`]: https://go-testdeep.zetta.rocks/operators/string/#cmpstring-shortcut
412416
[`CmpStruct`]: https://go-testdeep.zetta.rocks/operators/struct/#cmpstruct-shortcut
@@ -471,6 +475,8 @@ See [FAQ](https://go-testdeep.zetta.rocks/faq/).
471475
[`T.Shallow`]: https://go-testdeep.zetta.rocks/operators/shallow/#tshallow-shortcut
472476
[`T.Slice`]: https://go-testdeep.zetta.rocks/operators/slice/#tslice-shortcut
473477
[`T.Smuggle`]: https://go-testdeep.zetta.rocks/operators/smuggle/#tsmuggle-shortcut
478+
[`T.Sort`]: https://go-testdeep.zetta.rocks/operators/sort/#tsort-shortcut
479+
[`T.Sorted`]: https://go-testdeep.zetta.rocks/operators/sorted/#tsorted-shortcut
474480
[`T.SStruct`]: https://go-testdeep.zetta.rocks/operators/sstruct/#tsstruct-shortcut
475481
[`T.String`]: https://go-testdeep.zetta.rocks/operators/string/#tstring-shortcut
476482
[`T.Struct`]: https://go-testdeep.zetta.rocks/operators/struct/#tstruct-shortcut

td/check_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ type expectedErrorMatch struct {
7171
Contain string
7272
}
7373

74+
func ptr(x any) any {
75+
v := reflect.New(reflect.TypeOf(x))
76+
v.Elem().Set(reflect.ValueOf(x))
77+
return v.Interface()
78+
}
79+
7480
func mustBe(str string) expectedErrorMatch {
7581
return expectedErrorMatch{Exact: str}
7682
}

td/cmp_funcs.go

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"time"
1313
)
1414

15-
// allOperators lists the 67 operators.
15+
// allOperators lists the 69 operators.
1616
// nil means not usable in JSON().
1717
var allOperators = map[string]any{
1818
"All": All,
@@ -67,6 +67,8 @@ var allOperators = map[string]any{
6767
"Shallow": nil,
6868
"Slice": nil,
6969
"Smuggle": nil,
70+
"Sort": Sort,
71+
"Sorted": Sorted,
7072
"String": nil,
7173
"Struct": nil,
7274
"SubBagOf": SubBagOf,
@@ -1108,6 +1110,52 @@ func CmpSmuggle(t TestingT, got, fn, expectedValue any, args ...any) bool {
11081110
return Cmp(t, got, Smuggle(fn, expectedValue), args...)
11091111
}
11101112

1113+
// CmpSort is a shortcut for:
1114+
//
1115+
// td.Cmp(t, got, td.Sort(how, expectedValue), args...)
1116+
//
1117+
// See [Sort] for details.
1118+
//
1119+
// Returns true if the test is OK, false if it fails.
1120+
//
1121+
// If t is a [*T] then its Config field is inherited.
1122+
//
1123+
// args... are optional and allow to name the test. This name is
1124+
// used in case of failure to qualify the test. If len(args) > 1 and
1125+
// the first item of args is a string and contains a '%' rune then
1126+
// [fmt.Fprintf] is used to compose the name, else args are passed to
1127+
// [fmt.Fprint]. Do not forget it is the name of the test, not the
1128+
// reason of a potential failure.
1129+
func CmpSort(t TestingT, got, how, expectedValue any, args ...any) bool {
1130+
t.Helper()
1131+
return Cmp(t, got, Sort(how, expectedValue), args...)
1132+
}
1133+
1134+
// CmpSorted is a shortcut for:
1135+
//
1136+
// td.Cmp(t, got, td.Sorted(how), args...)
1137+
//
1138+
// See [Sorted] for details.
1139+
//
1140+
// [Sorted] optional parameter how is here mandatory.
1141+
// nil value should be passed to mimic its absence in
1142+
// original [Sorted] call.
1143+
//
1144+
// Returns true if the test is OK, false if it fails.
1145+
//
1146+
// If t is a [*T] then its Config field is inherited.
1147+
//
1148+
// args... are optional and allow to name the test. This name is
1149+
// used in case of failure to qualify the test. If len(args) > 1 and
1150+
// the first item of args is a string and contains a '%' rune then
1151+
// [fmt.Fprintf] is used to compose the name, else args are passed to
1152+
// [fmt.Fprint]. Do not forget it is the name of the test, not the
1153+
// reason of a potential failure.
1154+
func CmpSorted(t TestingT, got, how any, args ...any) bool {
1155+
t.Helper()
1156+
return Cmp(t, got, Sorted(how), args...)
1157+
}
1158+
11111159
// CmpSStruct is a shortcut for:
11121160
//
11131161
// td.Cmp(t, got, td.SStruct(model, expectedFields), args...)

td/example_cmp_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3101,6 +3101,42 @@ func ExampleCmpSmuggle_field_path() {
31013101
// check fields-path including maps/slices: true
31023102
}
31033103

3104+
func ExampleCmpSort_basic() {
3105+
t := &testing.T{}
3106+
3107+
got := []int{-1, 1, 2, -3, 3, -2, 0}
3108+
3109+
ok := td.CmpSort(t, got, 1, []int{-3, -2, -1, 0, 1, 2, 3})
3110+
fmt.Println("asc order:", ok)
3111+
3112+
ok = td.CmpSort(t, got, -1, []int{3, 2, 1, 0, -1, -2, -3})
3113+
fmt.Println("desc order:", ok)
3114+
3115+
// Output:
3116+
// asc order: true
3117+
// desc order: true
3118+
}
3119+
3120+
func ExampleCmpSorted_basic() {
3121+
t := &testing.T{}
3122+
3123+
got := []int{-3, -2, -1, 0, 1, 2, 3}
3124+
3125+
ok := td.CmpSorted(t, got, nil)
3126+
fmt.Println("is asc order (default):", ok)
3127+
3128+
ok = td.CmpSorted(t, got, 1)
3129+
fmt.Println("is asc order:", ok)
3130+
3131+
ok = td.CmpSorted(t, got, -1)
3132+
fmt.Println("is desc order:", ok)
3133+
3134+
// Output:
3135+
// is asc order (default): true
3136+
// is asc order: true
3137+
// is desc order: false
3138+
}
3139+
31043140
func ExampleCmpSStruct() {
31053141
t := &testing.T{}
31063142

td/example_t_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3101,6 +3101,42 @@ func ExampleT_Smuggle_field_path() {
31013101
// check fields-path including maps/slices: true
31023102
}
31033103

3104+
func ExampleT_Sort_basic() {
3105+
t := td.NewT(&testing.T{})
3106+
3107+
got := []int{-1, 1, 2, -3, 3, -2, 0}
3108+
3109+
ok := t.Sort(got, 1, []int{-3, -2, -1, 0, 1, 2, 3})
3110+
fmt.Println("asc order:", ok)
3111+
3112+
ok = t.Sort(got, -1, []int{3, 2, 1, 0, -1, -2, -3})
3113+
fmt.Println("desc order:", ok)
3114+
3115+
// Output:
3116+
// asc order: true
3117+
// desc order: true
3118+
}
3119+
3120+
func ExampleT_Sorted_basic() {
3121+
t := td.NewT(&testing.T{})
3122+
3123+
got := []int{-3, -2, -1, 0, 1, 2, 3}
3124+
3125+
ok := t.Sorted(got, nil)
3126+
fmt.Println("is asc order (default):", ok)
3127+
3128+
ok = t.Sorted(got, 1)
3129+
fmt.Println("is asc order:", ok)
3130+
3131+
ok = t.Sorted(got, -1)
3132+
fmt.Println("is desc order:", ok)
3133+
3134+
// Output:
3135+
// is asc order (default): true
3136+
// is asc order: true
3137+
// is desc order: false
3138+
}
3139+
31043140
func ExampleT_SStruct() {
31053141
t := td.NewT(&testing.T{})
31063142

td/example_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3139,6 +3139,42 @@ func ExampleSlice_typedSlice() {
31393139
// true
31403140
}
31413141

3142+
func ExampleSort_basic() {
3143+
t := &testing.T{}
3144+
3145+
got := []int{-1, 1, 2, -3, 3, -2, 0}
3146+
3147+
ok := td.Cmp(t, got, td.Sort(1, []int{-3, -2, -1, 0, 1, 2, 3}))
3148+
fmt.Println("asc order:", ok)
3149+
3150+
ok = td.Cmp(t, got, td.Sort(-1, []int{3, 2, 1, 0, -1, -2, -3}))
3151+
fmt.Println("desc order:", ok)
3152+
3153+
// Output:
3154+
// asc order: true
3155+
// desc order: true
3156+
}
3157+
3158+
func ExampleSorted_basic() {
3159+
t := &testing.T{}
3160+
3161+
got := []int{-3, -2, -1, 0, 1, 2, 3}
3162+
3163+
ok := td.Cmp(t, got, td.Sorted())
3164+
fmt.Println("is asc order (default):", ok)
3165+
3166+
ok = td.Cmp(t, got, td.Sorted(1))
3167+
fmt.Println("is asc order:", ok)
3168+
3169+
ok = td.Cmp(t, got, td.Sorted(-1))
3170+
fmt.Println("is desc order:", ok)
3171+
3172+
// Output:
3173+
// is asc order (default): true
3174+
// is asc order: true
3175+
// is desc order: false
3176+
}
3177+
31423178
func ExampleSuperSliceOf_array() {
31433179
t := &testing.T{}
31443180

td/t.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -940,6 +940,48 @@ func (t *T) Smuggle(got, fn, expectedValue any, args ...any) bool {
940940
return t.Cmp(got, Smuggle(fn, expectedValue), args...)
941941
}
942942

943+
// Sort is a shortcut for:
944+
//
945+
// t.Cmp(got, td.Sort(how, expectedValue), args...)
946+
//
947+
// See [Sort] for details.
948+
//
949+
// Returns true if the test is OK, false if it fails.
950+
//
951+
// args... are optional and allow to name the test. This name is
952+
// used in case of failure to qualify the test. If len(args) > 1 and
953+
// the first item of args is a string and contains a '%' rune then
954+
// [fmt.Fprintf] is used to compose the name, else args are passed to
955+
// [fmt.Fprint]. Do not forget it is the name of the test, not the
956+
// reason of a potential failure.
957+
func (t *T) Sort(got, how, expectedValue any, args ...any) bool {
958+
t.Helper()
959+
return t.Cmp(got, Sort(how, expectedValue), args...)
960+
}
961+
962+
// Sorted is a shortcut for:
963+
//
964+
// t.Cmp(got, td.Sorted(how), args...)
965+
//
966+
// See [Sorted] for details.
967+
//
968+
// [Sorted] optional parameter how is here mandatory.
969+
// nil value should be passed to mimic its absence in
970+
// original [Sorted] call.
971+
//
972+
// Returns true if the test is OK, false if it fails.
973+
//
974+
// args... are optional and allow to name the test. This name is
975+
// used in case of failure to qualify the test. If len(args) > 1 and
976+
// the first item of args is a string and contains a '%' rune then
977+
// [fmt.Fprintf] is used to compose the name, else args are passed to
978+
// [fmt.Fprint]. Do not forget it is the name of the test, not the
979+
// reason of a potential failure.
980+
func (t *T) Sorted(got, how any, args ...any) bool {
981+
t.Helper()
982+
return t.Cmp(got, Sorted(how), args...)
983+
}
984+
943985
// SStruct is a shortcut for:
944986
//
945987
// t.Cmp(got, td.SStruct(model, expectedFields), args...)

0 commit comments

Comments
 (0)