Skip to content

Commit

Permalink
feat: add Sort and Sorted operators
Browse files Browse the repository at this point in the history
Signed-off-by: Maxime Soulé <[email protected]>
  • Loading branch information
maxatome committed Aug 21, 2024
1 parent 2c70389 commit f0d6e43
Show file tree
Hide file tree
Showing 11 changed files with 1,086 additions and 2 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,8 @@ See [FAQ](https://go-testdeep.zetta.rocks/faq/).
[`Shallow`]: https://go-testdeep.zetta.rocks/operators/shallow/
[`Slice`]: https://go-testdeep.zetta.rocks/operators/slice/
[`Smuggle`]: https://go-testdeep.zetta.rocks/operators/smuggle/
[`Sort`]: https://go-testdeep.zetta.rocks/operators/sort/
[`Sorted`]: https://go-testdeep.zetta.rocks/operators/sorted/
[`SStruct`]: https://go-testdeep.zetta.rocks/operators/sstruct/
[`String`]: https://go-testdeep.zetta.rocks/operators/string/
[`Struct`]: https://go-testdeep.zetta.rocks/operators/struct/
Expand Down Expand Up @@ -407,6 +409,8 @@ See [FAQ](https://go-testdeep.zetta.rocks/faq/).
[`CmpShallow`]: https://go-testdeep.zetta.rocks/operators/shallow/#cmpshallow-shortcut
[`CmpSlice`]: https://go-testdeep.zetta.rocks/operators/slice/#cmpslice-shortcut
[`CmpSmuggle`]: https://go-testdeep.zetta.rocks/operators/smuggle/#cmpsmuggle-shortcut
[`CmpSort`]: https://go-testdeep.zetta.rocks/operators/sort/#cmpsort-shortcut
[`CmpSorted`]: https://go-testdeep.zetta.rocks/operators/sorted/#cmpsorted-shortcut
[`CmpSStruct`]: https://go-testdeep.zetta.rocks/operators/sstruct/#cmpsstruct-shortcut
[`CmpString`]: https://go-testdeep.zetta.rocks/operators/string/#cmpstring-shortcut
[`CmpStruct`]: https://go-testdeep.zetta.rocks/operators/struct/#cmpstruct-shortcut
Expand Down Expand Up @@ -471,6 +475,8 @@ See [FAQ](https://go-testdeep.zetta.rocks/faq/).
[`T.Shallow`]: https://go-testdeep.zetta.rocks/operators/shallow/#tshallow-shortcut
[`T.Slice`]: https://go-testdeep.zetta.rocks/operators/slice/#tslice-shortcut
[`T.Smuggle`]: https://go-testdeep.zetta.rocks/operators/smuggle/#tsmuggle-shortcut
[`T.Sort`]: https://go-testdeep.zetta.rocks/operators/sort/#tsort-shortcut
[`T.Sorted`]: https://go-testdeep.zetta.rocks/operators/sorted/#tsorted-shortcut
[`T.SStruct`]: https://go-testdeep.zetta.rocks/operators/sstruct/#tsstruct-shortcut
[`T.String`]: https://go-testdeep.zetta.rocks/operators/string/#tstring-shortcut
[`T.Struct`]: https://go-testdeep.zetta.rocks/operators/struct/#tstruct-shortcut
Expand Down
6 changes: 6 additions & 0 deletions td/check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ type expectedErrorMatch struct {
Contain string
}

func ptr(x any) any {
v := reflect.New(reflect.TypeOf(x))
v.Elem().Set(reflect.ValueOf(x))
return v.Interface()
}

func mustBe(str string) expectedErrorMatch {
return expectedErrorMatch{Exact: str}
}
Expand Down
50 changes: 49 additions & 1 deletion td/cmp_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"time"
)

// allOperators lists the 67 operators.
// allOperators lists the 69 operators.
// nil means not usable in JSON().
var allOperators = map[string]any{
"All": All,
Expand Down Expand Up @@ -67,6 +67,8 @@ var allOperators = map[string]any{
"Shallow": nil,
"Slice": nil,
"Smuggle": nil,
"Sort": Sort,
"Sorted": Sorted,
"String": nil,
"Struct": nil,
"SubBagOf": SubBagOf,
Expand Down Expand Up @@ -1108,6 +1110,52 @@ func CmpSmuggle(t TestingT, got, fn, expectedValue any, args ...any) bool {
return Cmp(t, got, Smuggle(fn, expectedValue), args...)
}

// CmpSort is a shortcut for:
//
// td.Cmp(t, got, td.Sort(how, expectedValue), args...)
//
// See [Sort] for details.
//
// Returns true if the test is OK, false if it fails.
//
// If t is a [*T] then its Config field is inherited.
//
// args... are optional and allow to name the test. This name is
// used in case of failure to qualify the test. If len(args) > 1 and
// the first item of args is a string and contains a '%' rune then
// [fmt.Fprintf] is used to compose the name, else args are passed to
// [fmt.Fprint]. Do not forget it is the name of the test, not the
// reason of a potential failure.
func CmpSort(t TestingT, got, how, expectedValue any, args ...any) bool {
t.Helper()
return Cmp(t, got, Sort(how, expectedValue), args...)
}

// CmpSorted is a shortcut for:
//
// td.Cmp(t, got, td.Sorted(how), args...)
//
// See [Sorted] for details.
//
// [Sorted] optional parameter how is here mandatory.
// nil value should be passed to mimic its absence in
// original [Sorted] call.
//
// Returns true if the test is OK, false if it fails.
//
// If t is a [*T] then its Config field is inherited.
//
// args... are optional and allow to name the test. This name is
// used in case of failure to qualify the test. If len(args) > 1 and
// the first item of args is a string and contains a '%' rune then
// [fmt.Fprintf] is used to compose the name, else args are passed to
// [fmt.Fprint]. Do not forget it is the name of the test, not the
// reason of a potential failure.
func CmpSorted(t TestingT, got, how any, args ...any) bool {
t.Helper()
return Cmp(t, got, Sorted(how), args...)
}

// CmpSStruct is a shortcut for:
//
// td.Cmp(t, got, td.SStruct(model, expectedFields), args...)
Expand Down
36 changes: 36 additions & 0 deletions td/example_cmp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3101,6 +3101,42 @@ func ExampleCmpSmuggle_field_path() {
// check fields-path including maps/slices: true
}

func ExampleCmpSort_basic() {
t := &testing.T{}

got := []int{-1, 1, 2, -3, 3, -2, 0}

ok := td.CmpSort(t, got, 1, []int{-3, -2, -1, 0, 1, 2, 3})
fmt.Println("asc order:", ok)

ok = td.CmpSort(t, got, -1, []int{3, 2, 1, 0, -1, -2, -3})
fmt.Println("desc order:", ok)

// Output:
// asc order: true
// desc order: true
}

func ExampleCmpSorted_basic() {
t := &testing.T{}

got := []int{-3, -2, -1, 0, 1, 2, 3}

ok := td.CmpSorted(t, got, nil)
fmt.Println("is asc order (default):", ok)

ok = td.CmpSorted(t, got, 1)
fmt.Println("is asc order:", ok)

ok = td.CmpSorted(t, got, -1)
fmt.Println("is desc order:", ok)

// Output:
// is asc order (default): true
// is asc order: true
// is desc order: false
}

func ExampleCmpSStruct() {
t := &testing.T{}

Expand Down
36 changes: 36 additions & 0 deletions td/example_t_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3101,6 +3101,42 @@ func ExampleT_Smuggle_field_path() {
// check fields-path including maps/slices: true
}

func ExampleT_Sort_basic() {
t := td.NewT(&testing.T{})

got := []int{-1, 1, 2, -3, 3, -2, 0}

ok := t.Sort(got, 1, []int{-3, -2, -1, 0, 1, 2, 3})
fmt.Println("asc order:", ok)

ok = t.Sort(got, -1, []int{3, 2, 1, 0, -1, -2, -3})
fmt.Println("desc order:", ok)

// Output:
// asc order: true
// desc order: true
}

func ExampleT_Sorted_basic() {
t := td.NewT(&testing.T{})

got := []int{-3, -2, -1, 0, 1, 2, 3}

ok := t.Sorted(got, nil)
fmt.Println("is asc order (default):", ok)

ok = t.Sorted(got, 1)
fmt.Println("is asc order:", ok)

ok = t.Sorted(got, -1)
fmt.Println("is desc order:", ok)

// Output:
// is asc order (default): true
// is asc order: true
// is desc order: false
}

func ExampleT_SStruct() {
t := td.NewT(&testing.T{})

Expand Down
36 changes: 36 additions & 0 deletions td/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3139,6 +3139,42 @@ func ExampleSlice_typedSlice() {
// true
}

func ExampleSort_basic() {
t := &testing.T{}

got := []int{-1, 1, 2, -3, 3, -2, 0}

ok := td.Cmp(t, got, td.Sort(1, []int{-3, -2, -1, 0, 1, 2, 3}))
fmt.Println("asc order:", ok)

ok = td.Cmp(t, got, td.Sort(-1, []int{3, 2, 1, 0, -1, -2, -3}))
fmt.Println("desc order:", ok)

// Output:
// asc order: true
// desc order: true
}

func ExampleSorted_basic() {
t := &testing.T{}

got := []int{-3, -2, -1, 0, 1, 2, 3}

ok := td.Cmp(t, got, td.Sorted())
fmt.Println("is asc order (default):", ok)

ok = td.Cmp(t, got, td.Sorted(1))
fmt.Println("is asc order:", ok)

ok = td.Cmp(t, got, td.Sorted(-1))
fmt.Println("is desc order:", ok)

// Output:
// is asc order (default): true
// is asc order: true
// is desc order: false
}

func ExampleSuperSliceOf_array() {
t := &testing.T{}

Expand Down
42 changes: 42 additions & 0 deletions td/t.go
Original file line number Diff line number Diff line change
Expand Up @@ -940,6 +940,48 @@ func (t *T) Smuggle(got, fn, expectedValue any, args ...any) bool {
return t.Cmp(got, Smuggle(fn, expectedValue), args...)
}

// Sort is a shortcut for:
//
// t.Cmp(got, td.Sort(how, expectedValue), args...)
//
// See [Sort] for details.
//
// Returns true if the test is OK, false if it fails.
//
// args... are optional and allow to name the test. This name is
// used in case of failure to qualify the test. If len(args) > 1 and
// the first item of args is a string and contains a '%' rune then
// [fmt.Fprintf] is used to compose the name, else args are passed to
// [fmt.Fprint]. Do not forget it is the name of the test, not the
// reason of a potential failure.
func (t *T) Sort(got, how, expectedValue any, args ...any) bool {
t.Helper()
return t.Cmp(got, Sort(how, expectedValue), args...)
}

// Sorted is a shortcut for:
//
// t.Cmp(got, td.Sorted(how), args...)
//
// See [Sorted] for details.
//
// [Sorted] optional parameter how is here mandatory.
// nil value should be passed to mimic its absence in
// original [Sorted] call.
//
// Returns true if the test is OK, false if it fails.
//
// args... are optional and allow to name the test. This name is
// used in case of failure to qualify the test. If len(args) > 1 and
// the first item of args is a string and contains a '%' rune then
// [fmt.Fprintf] is used to compose the name, else args are passed to
// [fmt.Fprint]. Do not forget it is the name of the test, not the
// reason of a potential failure.
func (t *T) Sorted(got, how any, args ...any) bool {
t.Helper()
return t.Cmp(got, Sorted(how), args...)
}

// SStruct is a shortcut for:
//
// t.Cmp(got, td.SStruct(model, expectedFields), args...)
Expand Down
Loading

0 comments on commit f0d6e43

Please sign in to comment.