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

feat: add new helpers to p/uassert #2547

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions examples/gno.land/p/demo/uassert/helpers.gno
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,159 @@ func checkDidPanic(f func()) (didPanic bool, message string) {
didPanic = false
return
}

func compare(t TestingT, e1, e2 interface{}) int {
t.Helper()
switch v1 := e1.(type) {
case int:
v2 := e2.(int)
Copy link
Contributor

Choose a reason for hiding this comment

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

Any of these type assertions can fail if the underlying types of e1 and e2 are not the same. This behavior is not consistent with the behavior of the testify package this is modeled after. Instead, it should fail will an error message that types are incompatible, or something of that equivalence.

if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
case int8:
v2 := e2.(int8)
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
case int16:
v2 := e2.(int16)
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
case int32:
v2 := e2.(int32)
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
case int64:
v2 := e2.(int64)
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
case uint:
v2 := e2.(uint)
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
case uint8:
v2 := e2.(uint8)
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
case uint16:
v2 := e2.(uint16)
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
case uint32:
v2 := e2.(uint32)
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
case uint64:
v2 := e2.(uint64)
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
case float32:
v2 := e2.(float32)
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
case float64:
v2 := e2.(float64)
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
case string:
v2 := e2.(string)
if v1 > v2 {
return 1
} else if v1 < v2 {
return -1
}
return 0
default:
fail(t, []string{}, "compare: unsupported type")
return 0
}
}

func isNil(object interface{}) bool {
if object == nil {
return true
}

switch v := object.(type) {
case *int, *int8, *int16, *int32, *int64:
Copy link
Contributor

Choose a reason for hiding this comment

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

Type switch cases with multiple types won't work -- v will continue to be an interface type so it will evaluate to not nil because the underlying nil value is typed. Each of the types must be on its own separate line. Here is an example of this behavior: https://play.gno.land/p/wTCoLeDZiMb

return v == nil
case *uint, *uint8, *uint16, *uint32, *uint64:
return v == nil
case *float32, *float64:
return v == nil
case *string:
return v == nil
case *bool:
return v == nil
case *[]int, *[]string, *[]float64, *[]bool:
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should support slices of all primitive types rather than a select few; there aren't that many.

return v == nil
case *map[string]int, *map[string]string, *map[string]bool:
Copy link
Contributor

Choose a reason for hiding this comment

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

There are quite a few map combinations to deal with. How do we choose which to support? It seems inconvenient for anyone using this package to have to know which are supported and which are not.

return v == nil
case *func():
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure how useful this one is; an empty function is only of the the infinite types of function signatures. Maybe better to keep functions as unsupported types.

return v == nil
case []int:
Copy link
Contributor

Choose a reason for hiding this comment

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

Slice values need to be compared to nil, not have their length checked. A nil slice will always have a length of zero, but non-nil slices of length zero can exist.

return len(v) == 0
case []string:
return len(v) == 0
case []float64:
return len(v) == 0
case []bool:
return len(v) == 0
case map[string]int:
Copy link
Contributor

Choose a reason for hiding this comment

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

Same applies to maps as for slices; it needs to be compared to nil as both nil and non-nil maps can have a length of zero.

return len(v) == 0
case map[string]string:
return len(v) == 0
case map[string]bool:
return len(v) == 0
case func():
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as above in regards to whether this should support functions types.

return v == nil
default:
Copy link
Contributor

Choose a reason for hiding this comment

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

The default should specify why it failed -- this is an unsupported type.

return false
}
}
Loading
Loading