Skip to content

Commit

Permalink
Merge pull request #11 from iostrovok/more_conditions
Browse files Browse the repository at this point in the history
More conditions: lessThan, moreThan, moreOrEqualThan, lessOrEqualThan
  • Loading branch information
iostrovok committed Oct 4, 2021
2 parents f89131c + e4386c0 commit 4b2d431
Show file tree
Hide file tree
Showing 6 changed files with 497 additions and 7 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ _*
*.[568]
[568].out

go.sum

.idea/
vendor/
check_test.o
Expand Down
2 changes: 1 addition & 1 deletion check.go
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ type resultTracker struct {
func newResultTracker() *resultTracker {
return &resultTracker{_expectChan: make(chan *C), // Synchronous
_doneChan: make(chan *C, 32), // Asynchronous
_stopChan: make(chan bool)} // Synchronous
_stopChan: make(chan bool)} // Synchronous
}

func (tracker *resultTracker) start() {
Expand Down
362 changes: 362 additions & 0 deletions checkers.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"regexp"
"strings"

cf "github.com/iostrovok/go-convert"
"github.com/niemeyer/pretty"
)

Expand Down Expand Up @@ -214,6 +215,15 @@ func formatUnequal(obtained interface{}, expected interface{}) string {
%s`, formatMultiLine(strings.Join(diff, "\n"), false))
}

func formatUnsupportedType(params []interface{}) string {
out := "Comparing incomparable type " +
reflect.ValueOf(params[0]).Type().String() +
" and " +
reflect.ValueOf(params[1]).Type().String()

return out
}

type equalsChecker struct {
*CheckerInfo
}
Expand Down Expand Up @@ -526,3 +536,355 @@ func (checker *implementsChecker) Check(params []interface{}, names []string) (r
}
return obtained.Type().Implements(ifaceptr.Elem().Type()), ""
}

// -----------------------------------------------------------------------
// MoreThan checker.

var NoMoreThanStringError = "Difference: first (string) parameter <= (string) second, expect more"

type moreThan struct {
*CheckerInfo
}

// The MoreThan checker tests whether the obtained value is more than value.
//
// For example:
//
// c.Assert(v1, MoreThan, v2) -> v1 > v2
// c.Assert(v1, LessThan, 23) -> v1 > 23
// c.Assert(v1, LessThan, "my string") -> v1 > "my string"
// c.Assert(v1, LessThan, []byte("my string")) -> string(v1) > "my string"
//
// defaults conversion for checking:
// Int, Int8, Int16, Int32, Int64 => Int64
// Uint, Uint8, Uint16, Uint32, Uint64 => Uint64
// float32 => float32
// []byte, string => string
// float64 => float64
//

var MoreThan Checker = &moreThan{
&CheckerInfo{Name: "MoreThan", Params: []string{"get", "should be more"}},
}

func (checker *moreThan) Check(params []interface{}, names []string) (result bool, error string) {
defer func() {
if v := recover(); v != nil {
result = false
error = fmt.Sprint(v)
} else if !result && error == "" {
error = fmt.Sprintf("Difference: %v <= %v", params[0], params[1])
}
}()

if a := []bool{isStringType(params[0]), isStringType(params[1])}; a[0] || a[1] {
if a[0] && a[1] {
if result = cf.String(params[0]) > cf.String(params[1]); !result {
error = "First (string) parameter equals (string) second, expect more"

// generic diff
if diff := pretty.Diff(cf.String(params[0]), cf.String(params[1])); len(diff) > 0 {
error = NoLessThanStringError
}
}
} else {
error = formatUnsupportedType(params)
}
return
}

rt := reflect.ValueOf(params[0]).Kind()
if rt == reflect.Ptr {
rt = reflect.ValueOf(params[0]).Type().Kind()
}

rt2 := reflect.ValueOf(params[1]).Kind()
if rt2 == reflect.Ptr {
rt2 = reflect.ValueOf(params[1]).Type().Kind()
}

// unsupported types
if rt != rt2 {
if reflect.Float32 == rt || reflect.Float32 == rt2 || reflect.Float64 == rt || reflect.Float64 == rt2 {
error = formatUnsupportedType(params)
return
}
}

switch rt {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
result = cf.Int64(params[0]) > cf.Int64(params[1])
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
result = cf.Uint64(params[0]) > cf.Uint64(params[1])
case reflect.Float32:
result = cf.Float32(params[0]) > cf.Float32(params[1])
case reflect.Float64:
result = cf.Float64(params[0]) > cf.Float64(params[1])
default:
error = formatUnsupportedType(params)
}

return
}

// -----------------------------------------------------------------------
// LessThan checker.

var NoLessThanStringError = "Difference: first (string) parameter <= (string) second, expect less"

type lessThan struct {
*CheckerInfo
}

// The LessThan checker tests whether the obtained value is less than value.
//
// For example:
//
// c.Assert(v1, LessThan, v2) -> v1 < v2
// c.Assert(v1, LessThan, 23) -> v1 < 23
// c.Assert(v1, LessThan, "my string") -> v1 < "my string"
// c.Assert(v1, LessThan, []byte("my string")) -> string(v1) < "my string"
//
// defaults conversion for checking:
// Int, Int8, Int16, Int32, Int64 => Int64
// Uint, Uint8, Uint16, Uint32, Uint64 => Uint64
// float32 => float32
// []byte, string => string
// float64 => float64
//

var LessThan Checker = &lessThan{
&CheckerInfo{Name: "LessThan", Params: []string{"get", "should be less"}},
}

func (checker *lessThan) Check(params []interface{}, names []string) (result bool, error string) {
defer func() {
if v := recover(); v != nil {
result = false
error = fmt.Sprint(v)
} else if !result && error == "" {
error = fmt.Sprintf("Difference: %v >= %v", params[0], params[1])
}
}()

if a := []bool{isStringType(params[0]), isStringType(params[1])}; a[0] || a[1] {
if a[0] && a[1] {
result = cf.String(params[0]) < cf.String(params[1])
if !result {
// generic diff
if diff := pretty.Diff(cf.String(params[0]), cf.String(params[1])); len(diff) > 0 {
error = NoLessThanStringError
} else {
error = "First (string) parameter equals (string) second, expect less"
}
}
} else {
error = formatUnsupportedType(params)
}
return
}

rt := reflect.ValueOf(params[0]).Kind()
if rt == reflect.Ptr {
rt = reflect.ValueOf(params[0]).Type().Kind()
}

rt2 := reflect.ValueOf(params[1]).Kind()
if rt2 == reflect.Ptr {
rt2 = reflect.ValueOf(params[1]).Type().Kind()
}

// unsupported types
if rt != rt2 {
if reflect.Float32 == rt || reflect.Float32 == rt2 || reflect.Float64 == rt || reflect.Float64 == rt2 {
error = formatUnsupportedType(params)
return
}
}

switch rt {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
result = cf.Int64(params[0]) < cf.Int64(params[1])
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
result = cf.Uint64(params[0]) < cf.Uint64(params[1])
case reflect.Float32:
result = cf.Float32(params[0]) < cf.Float32(params[1])
case reflect.Float64:
result = cf.Float64(params[0]) < cf.Float64(params[1])
default:
error = formatUnsupportedType(params)
}

return
}

// -----------------------------------------------------------------------
// MoreOrEqualThan checker.

var NoMoreOrEqualThanStringError = "Difference: first (string) parameter > (string) second, expect less or equal"

type moreOrEqualThan struct {
*CheckerInfo
}

// The MoreOrEqualThan checker tests whether the obtained value is less than value.
//
// For example:
//
// c.Assert(v1, MoreOrEqualThan, v2) -> v1 = v2
// c.Assert(v1, MoreOrEqualThan, 23) -> v1 >= 23
// c.Assert(v1, MoreOrEqualThan, "my string") -> v1 >= "my string"
// c.Assert(v1, MoreOrEqualThan, []byte("my string")) -> string(v1) >= "my string"
//
// defaults conversion for checking:
// Int, Int8, Int16, Int32, Int64 => Int64
// Uint, Uint8, Uint16, Uint32, Uint64 => Uint64
// float32 => float32
// []byte, string => string
// float64 => float64
//

var MoreOrEqualThan Checker = &moreOrEqualThan{
&CheckerInfo{Name: "MoreOrEqualThan", Params: []string{"get", "should be more or equal than"}},
}

func (checker *moreOrEqualThan) Check(params []interface{}, names []string) (result bool, error string) {
defer func() {
if v := recover(); v != nil {
result = false
error = fmt.Sprint(v)
} else if !result && error == "" {
error = fmt.Sprintf("Difference: %v < %v", params[0], params[1])
}
}()

if a := []bool{isStringType(params[0]), isStringType(params[1])}; a[0] || a[1] {
if a[0] && a[1] {
if result = cf.String(params[0]) >= cf.String(params[1]); !result {
error = NoMoreOrEqualThanStringError
}
} else {
error = formatUnsupportedType(params)
}
return
}

rt := reflect.ValueOf(params[0]).Kind()
if rt == reflect.Ptr {
rt = reflect.ValueOf(params[0]).Type().Kind()
}

rt2 := reflect.ValueOf(params[1]).Kind()
if rt2 == reflect.Ptr {
rt2 = reflect.ValueOf(params[1]).Type().Kind()
}

// unsupported types
if rt != rt2 {
if reflect.Float32 == rt || reflect.Float32 == rt2 || reflect.Float64 == rt || reflect.Float64 == rt2 {
error = formatUnsupportedType(params)
return
}
}

switch rt {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
result = cf.Int64(params[0]) >= cf.Int64(params[1])
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
result = cf.Uint64(params[0]) >= cf.Uint64(params[1])
case reflect.Float32:
result = cf.Float32(params[0]) >= cf.Float32(params[1])
case reflect.Float64:
result = cf.Float64(params[0]) >= cf.Float64(params[1])
default:
error = formatUnsupportedType(params)
}

return
}

func isStringType(p interface{}) bool {
strName := reflect.ValueOf(p).Type().String()
return strName == "string" || strName == "[]uint8"
}

// -----------------------------------------------------------------------
// LessOrEqualThan checker.
var NoLessOrEqualThanStringError = "Difference: first (string) parameter > (string) second, expect less or equal"

type lessOrEqualThan struct {
*CheckerInfo
}

// The LessOrEqualThan checker tests whether the obtained value is less than value.
//
// For example:
//
// c.Assert(v1, LessOrEqualThan, 23) -> v1 <= v2
// c.Assert(v1, LessOrEqualThan, "my string") -> v1 <= v2
//
// defaults conversion for checking:
// Int, Int8, Int16, Int32, Int64 => Int64
// Uint, Uint8, Uint16, Uint32, Uint64 => Uint64
// float32 => float32
// []byte, string => string
// float64 => float64
//
var LessOrEqualThan Checker = &lessOrEqualThan{
&CheckerInfo{Name: "MoreOrEqualThan", Params: []string{"get", "should be more or equal than"}},
}

func (checker *lessOrEqualThan) Check(params []interface{}, names []string) (result bool, error string) {
defer func() {
if v := recover(); v != nil {
result = false
error = fmt.Sprint(v)
} else if !result && error == "" {
error = fmt.Sprintf("Difference: %v > %v", params[0], params[1])
}
}()

if a := []bool{isStringType(params[0]), isStringType(params[1])}; a[0] || a[1] {
if a[0] && a[1] {
if result = cf.String(params[0]) <= cf.String(params[1]); !result {
error = NoLessOrEqualThanStringError
}
} else {
error = formatUnsupportedType(params)
}
return
}

rt := reflect.ValueOf(params[0]).Kind()
if rt == reflect.Ptr {
rt = reflect.ValueOf(params[0]).Type().Kind()
}

rt2 := reflect.ValueOf(params[1]).Kind()
if rt2 == reflect.Ptr {
rt2 = reflect.ValueOf(params[1]).Type().Kind()
}

// unsupported types
if rt != rt2 {
if reflect.Float32 == rt || reflect.Float32 == rt2 || reflect.Float64 == rt || reflect.Float64 == rt2 {
error = formatUnsupportedType(params)
return
}
}

switch rt {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
result = cf.Int64(params[0]) <= cf.Int64(params[1])
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
result = cf.Uint64(params[0]) <= cf.Uint64(params[1])
case reflect.Float32:
result = cf.Float32(params[0]) <= cf.Float32(params[1])
case reflect.Float64:
result = cf.Float64(params[0]) <= cf.Float64(params[1])
default:
error = formatUnsupportedType(params)
}

return
}
Loading

0 comments on commit 4b2d431

Please sign in to comment.