PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/p/nt/uassert/v0

Package
Open in gnoweb ↗

Overview

Kind
Pure package
Name
v0
Namespace
nt / uassert
Files
8 (README)(gnomod.toml)
Exported functions
n/a — not supported for pure packages by the node (vm/qfuncs)
Module
gno.land/p/nt/uassert/v0
gno
0.9

Files (8)

  • README.mdmarkdown
  • gnomod.tomltoml
  • doc.gnogno
  • helpers.gnogno
  • types.gnogno
  • uassert.gnogno
  • mock_test.gnogno
  • uassert_test.gnogno
  • uassert.gnogno
    1// uassert is an adapted lighter version of https://github.com/stretchr/testify/assert.2package uassert34import (5	"errors"6	"strconv"7	"strings"8

    Functions

    not supported for pure packages by the node (vm/qfuncs)

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    9 "gno.land/p/nt/ufmt/v0"
    10 "gno.land/p/onbloc/diff/v0"
    11)
    12
    13// NoError asserts that a function returned no error (i.e. `nil`).
    14func NoError(t TestingT, err error, msgs ...string) bool {
    15 t.Helper()
    16 if err != nil {
    17 return fail(t, msgs, "unexpected error: %s", err.Error())
    18 }
    19 return true
    20}
    21
    22// Error asserts that a function returned an error (i.e. not `nil`).
    23func Error(t TestingT, err error, msgs ...string) bool {
    24 t.Helper()
    25 if err == nil {
    26 return fail(t, msgs, "an error is expected but got nil")
    27 }
    28 return true
    29}
    30
    31// ErrorContains asserts that a function returned an error (i.e. not `nil`)
    32// and that the error contains the specified substring.
    33func ErrorContains(t TestingT, err error, contains string, msgs ...string) bool {
    34 t.Helper()
    35
    36 if !Error(t, err, msgs...) {
    37 return false
    38 }
    39
    40 actual := err.Error()
    41 if !strings.Contains(actual, contains) {
    42 return fail(t, msgs, "error %q does not contain %q", actual, contains)
    43 }
    44
    45 return true
    46}
    47
    48// True asserts that the specified value is true.
    49func True(t TestingT, value bool, msgs ...string) bool {
    50 t.Helper()
    51 if !value {
    52 return fail(t, msgs, "should be true")
    53 }
    54 return true
    55}
    56
    57// False asserts that the specified value is false.
    58func False(t TestingT, value bool, msgs ...string) bool {
    59 t.Helper()
    60 if value {
    61 return fail(t, msgs, "should be false")
    62 }
    63 return true
    64}
    65
    66// ErrorIs asserts the given error matches the target error using errors.Is,
    67// which traverses the error chain looking for a match.
    68func ErrorIs(t TestingT, err, target error, msgs ...string) bool {
    69 t.Helper()
    70
    71 if !errors.Is(err, target) {
    72 return fail(t, msgs, "error mismatch, expected %s, got %s", target, err)
    73 }
    74
    75 return true
    76}
    77
    78// AbortsWithMessage asserts that the code inside the specified func aborts
    79// (panics when crossing another realm).
    80// Use PanicsWithMessage for asserting local panics within the same realm.
    81//
    82// `rlm` is threaded into the callback via cross(rlm) when f is func(realm).
    83// It is ignored for func() callbacks. /p/ production code cannot declare
    84// crossing functions, so rlm is taken as the second (non-first) parameter
    85// — callers pass `cur` directly.
    86//
    87// NOTE: This relies on gno's `revive` mechanism to catch aborts.
    88func AbortsWithMessage(t TestingT, rlm realm, msg string, f any, msgs ...string) bool {
    89 t.Helper()
    90
    91 var didAbort bool
    92 var abortValue any
    93 var r any
    94
    95 switch f := f.(type) {
    96 case func():
    97 r = revive(f) // revive() captures the value passed to panic()
    98 case func(realm):
    99 r = revive(func() { f(cross(rlm)) })
    100 default:
    101 panic("f must be of type func() or func(realm)")
    102 }
    103 if r != nil {
    104 didAbort = true
    105 abortValue = r
    106 }
    107
    108 if !didAbort {
    109 // If the function didn't abort as expected
    110 return fail(t, msgs, "func should abort")
    111 }
    112
    113 // Check if the abort value matches the expected message string
    114 abortStr := ufmt.Sprintf("%v", abortValue)
    115 if abortStr != msg {
    116 return fail(t, msgs, "func should abort with message:\t%q\n\tActual abort value:\t%q", msg, abortStr)
    117 }
    118
    119 // Success: function aborted with the expected message
    120 return true
    121}
    122
    123// AbortsContains asserts that the code inside the specified func aborts
    124// (panics when crossing another realm) and the abort message contains the specified substring.
    125// See AbortsWithMessage for `rlm` semantics.
    126func AbortsContains(t TestingT, rlm realm, substr string, f any, msgs ...string) bool {
    127 t.Helper()
    128
    129 var didAbort bool
    130 var abortValue any
    131 var r any
    132
    133 if fn, ok := f.(func()); ok {
    134 r = revive(fn)
    135 } else if fn, ok := f.(func(realm)); ok {
    136 r = revive(func() { fn(cross(rlm)) })
    137 } else {
    138 panic("f must be of type func() or func(realm)")
    139 }
    140 if r != nil {
    141 didAbort = true
    142 abortValue = r
    143 }
    144
    145 if !didAbort {
    146 return fail(t, msgs, "func should abort")
    147 }
    148
    149 abortStr := ufmt.Sprintf("%v", abortValue)
    150 if !strings.Contains(abortStr, substr) {
    151 return fail(t, msgs, "func should abort with message containing:\t%q\n\tActual abort value:\t%q", substr, abortStr)
    152 }
    153
    154 return true
    155}
    156
    157// NotAborts asserts that the code inside the specified func does NOT abort
    158// when crossing an execution boundary.
    159// Note: Consider using NotPanics which checks for both panics and aborts.
    160// See AbortsWithMessage for `rlm` semantics.
    161func NotAborts(t TestingT, rlm realm, f any, msgs ...string) bool {
    162 t.Helper()
    163
    164 var didAbort bool
    165 var abortValue any
    166 var r any
    167
    168 switch f := f.(type) {
    169 case func():
    170 r = revive(f) // revive() captures the value passed to panic()
    171 case func(realm):
    172 r = revive(func() { f(cross(rlm)) })
    173 default:
    174 panic("f must be of type func() or func(realm)")
    175 }
    176 if r != nil {
    177 didAbort = true
    178 abortValue = r
    179 }
    180
    181 if didAbort {
    182 // Fail if the function aborted when it shouldn't have
    183 // Attempt to format the abort value in the error message
    184 return fail(t, msgs, "func should not abort\\n\\tAbort value:\\t%v", abortValue)
    185 }
    186
    187 // Success: function did not abort
    188 return true
    189}
    190
    191// PanicsWithMessage asserts that the code inside the specified func panics
    192// locally within the same execution realm.
    193// Use AbortsWithMessage for asserting panics that cross execution boundaries (aborts).
    194// See AbortsWithMessage for `rlm` semantics.
    195func PanicsWithMessage(t TestingT, rlm realm, msg string, f any, msgs ...string) bool {
    196 t.Helper()
    197
    198 didPanic, panicValue := checkDidPanic(f, rlm)
    199 if !didPanic {
    200 return fail(t, msgs, "func should panic\n\tPanic value:\t%v", panicValue)
    201 }
    202
    203 // Check if the abort value matches the expected message string
    204 panicStr := ufmt.Sprintf("%v", panicValue)
    205 if panicStr != msg {
    206 return fail(t, msgs, "func should panic with message:\t%q\n\tActual panic value:\t%q", msg, panicStr)
    207 }
    208 return true
    209}
    210
    211// PanicsContains asserts that the code inside the specified func panics
    212// locally within the same execution realm and the panic message contains the specified substring.
    213// See AbortsWithMessage for `rlm` semantics.
    214func PanicsContains(t TestingT, rlm realm, substr string, f any, msgs ...string) bool {
    215 t.Helper()
    216
    217 didPanic, panicValue := checkDidPanic(f, rlm)
    218 if !didPanic {
    219 return fail(t, msgs, "func should panic\n\tPanic value:\t%v", panicValue)
    220 }
    221
    222 panicStr := ufmt.Sprintf("%v", panicValue)
    223 if !strings.Contains(panicStr, substr) {
    224 return fail(t, msgs, "func should panic with message containing:\t%q\n\tActual panic value:\t%q", substr, panicStr)
    225 }
    226 return true
    227}
    228
    229// NotPanics asserts that the code inside the specified func does NOT panic
    230// (within the same realm) or abort (due to a cross-realm panic).
    231// See AbortsWithMessage for `rlm` semantics.
    232func NotPanics(t TestingT, rlm realm, f any, msgs ...string) bool {
    233 t.Helper()
    234
    235 var panicVal any
    236 var didPanic bool
    237 var abortVal any
    238
    239 // Use revive to catch cross-realm aborts
    240 abortVal = revive(func() {
    241 // Use defer+recover to catch same-realm panics
    242 defer func() {
    243 if r := recover(); r != nil {
    244 didPanic = true
    245 panicVal = r
    246 }
    247 }()
    248 // Execute the function
    249 switch f := f.(type) {
    250 case func():
    251 f()
    252 case func(realm):
    253 f(cross(rlm))
    254 default:
    255 panic("f must be of type func() or func(realm)")
    256 }
    257 })
    258
    259 // Check if revive caught an abort
    260 if abortVal != nil {
    261 return fail(t, msgs, "func should not abort\n\tAbort value:\t%+v", abortVal)
    262 }
    263
    264 // Check if recover caught a panic
    265 if didPanic {
    266 // Format panic value for message
    267 panicMsg := ""
    268 if panicVal == nil {
    269 panicMsg = "nil"
    270 } else if err, ok := panicVal.(error); ok {
    271 panicMsg = err.Error()
    272 } else if str, ok := panicVal.(string); ok {
    273 panicMsg = str
    274 } else {
    275 // Fallback for other types
    276 panicMsg = "panic: unsupported type"
    277 }
    278 return fail(t, msgs, "func should not panic\n\tPanic value:\t%s", panicMsg)
    279 }
    280
    281 return true // No panic or abort occurred
    282}
    283
    284// Equal asserts that two objects are equal.
    285func Equal(t TestingT, expected, actual any, msgs ...string) bool {
    286 t.Helper()
    287
    288 if expected == nil || actual == nil {
    289 return expected == actual
    290 }
    291
    292 // XXX: errors
    293 // XXX: slices
    294 // XXX: pointers
    295
    296 equal := false
    297 ok_ := false
    298 es, as := "unsupported type", "unsupported type"
    299
    300 switch ev := expected.(type) {
    301 case string:
    302 if av, ok := actual.(string); ok {
    303 equal = ev == av
    304 ok_ = true
    305 es, as = ev, av
    306 if !equal {
    307 dif := diff.MyersDiff(ev, av)
    308 return fail(t, msgs, "uassert.Equal: strings are different\n\tDiff: %s", diff.Format(dif))
    309 }
    310 }
    311 case address:
    312 if av, ok := actual.(address); ok {
    313 equal = ev == av
    314 ok_ = true
    315 es, as = string(ev), string(av)
    316 }
    317 case int:
    318 if av, ok := actual.(int); ok {
    319 equal = ev == av
    320 ok_ = true
    321 es, as = strconv.Itoa(ev), strconv.Itoa(av)
    322 }
    323 case int8:
    324 if av, ok := actual.(int8); ok {
    325 equal = ev == av
    326 ok_ = true
    327 es, as = strconv.Itoa(int(ev)), strconv.Itoa(int(av))
    328 }
    329 case int16:
    330 if av, ok := actual.(int16); ok {
    331 equal = ev == av
    332 ok_ = true
    333 es, as = strconv.Itoa(int(ev)), strconv.Itoa(int(av))
    334 }
    335 case int32:
    336 if av, ok := actual.(int32); ok {
    337 equal = ev == av
    338 ok_ = true
    339 es, as = strconv.Itoa(int(ev)), strconv.Itoa(int(av))
    340 }
    341 case int64:
    342 if av, ok := actual.(int64); ok {
    343 equal = ev == av
    344 ok_ = true
    345 es, as = strconv.Itoa(int(ev)), strconv.Itoa(int(av))
    346 }
    347 case uint:
    348 if av, ok := actual.(uint); ok {
    349 equal = ev == av
    350 ok_ = true
    351 es, as = strconv.FormatUint(uint64(ev), 10), strconv.FormatUint(uint64(av), 10)
    352 }
    353 case uint8:
    354 if av, ok := actual.(uint8); ok {
    355 equal = ev == av
    356 ok_ = true
    357 es, as = strconv.FormatUint(uint64(ev), 10), strconv.FormatUint(uint64(av), 10)
    358 }
    359 case uint16:
    360 if av, ok := actual.(uint16); ok {
    361 equal = ev == av
    362 ok_ = true
    363 es, as = strconv.FormatUint(uint64(ev), 10), strconv.FormatUint(uint64(av), 10)
    364 }
    365 case uint32:
    366 if av, ok := actual.(uint32); ok {
    367 equal = ev == av
    368 ok_ = true
    369 es, as = strconv.FormatUint(uint64(ev), 10), strconv.FormatUint(uint64(av), 10)
    370 }
    371 case uint64:
    372 if av, ok := actual.(uint64); ok {
    373 equal = ev == av
    374 ok_ = true
    375 es, as = strconv.FormatUint(ev, 10), strconv.FormatUint(av, 10)
    376 }
    377 case bool:
    378 if av, ok := actual.(bool); ok {
    379 equal = ev == av
    380 ok_ = true
    381 if ev {
    382 es, as = "true", "false"
    383 } else {
    384 es, as = "false", "true"
    385 }
    386 }
    387 case float32:
    388 if av, ok := actual.(float32); ok {
    389 equal = ev == av
    390 ok_ = true
    391 }
    392 case float64:
    393 if av, ok := actual.(float64); ok {
    394 equal = ev == av
    395 ok_ = true
    396 }
    397 default:
    398 return fail(t, msgs, "uassert.Equal: unsupported type")
    399 }
    400
    401 /*
    402 // XXX: implement stringer and other well known similar interfaces
    403 type stringer interface{ String() string }
    404 if ev, ok := expected.(stringer); ok {
    405 if av, ok := actual.(stringer); ok {
    406 equal = ev.String() == av.String()
    407 ok_ = true
    408 }
    409 }
    410 */
    411
    412 if !ok_ {
    413 return fail(t, msgs, "uassert.Equal: different types") // XXX: display the types
    414 }
    415 if !equal {
    416 return fail(t, msgs, "uassert.Equal: same type but different value\n\texpected: %s\n\tactual: %s", es, as)
    417 }
    418
    419 return true
    420}
    421
    422// NotEqual asserts that two objects are not equal.
    423func NotEqual(t TestingT, expected, actual any, msgs ...string) bool {
    424 t.Helper()
    425
    426 if expected == nil || actual == nil {
    427 return expected != actual
    428 }
    429
    430 // XXX: errors
    431 // XXX: slices
    432 // XXX: pointers
    433
    434 notEqual := false
    435 ok_ := false
    436 es, as := "unsupported type", "unsupported type"
    437
    438 switch ev := expected.(type) {
    439 case string:
    440 if av, ok := actual.(string); ok {
    441 notEqual = ev != av
    442 ok_ = true
    443 es, as = ev, av
    444 }
    445 case address:
    446 if av, ok := actual.(address); ok {
    447 notEqual = ev != av
    448 ok_ = true
    449 es, as = string(ev), string(av)
    450 }
    451 case int:
    452 if av, ok := actual.(int); ok {
    453 notEqual = ev != av
    454 ok_ = true
    455 es, as = strconv.Itoa(ev), strconv.Itoa(av)
    456 }
    457 case int8:
    458 if av, ok := actual.(int8); ok {
    459 notEqual = ev != av
    460 ok_ = true
    461 es, as = strconv.Itoa(int(ev)), strconv.Itoa(int(av))
    462 }
    463 case int16:
    464 if av, ok := actual.(int16); ok {
    465 notEqual = ev != av
    466 ok_ = true
    467 es, as = strconv.Itoa(int(ev)), strconv.Itoa(int(av))
    468 }
    469 case int32:
    470 if av, ok := actual.(int32); ok {
    471 notEqual = ev != av
    472 ok_ = true
    473 es, as = strconv.Itoa(int(ev)), strconv.Itoa(int(av))
    474 }
    475 case int64:
    476 if av, ok := actual.(int64); ok {
    477 notEqual = ev != av
    478 ok_ = true
    479 es, as = strconv.Itoa(int(ev)), strconv.Itoa(int(av))
    480 }
    481 case uint:
    482 if av, ok := actual.(uint); ok {
    483 notEqual = ev != av
    484 ok_ = true
    485 es, as = strconv.FormatUint(uint64(ev), 10), strconv.FormatUint(uint64(av), 10)
    486 }
    487 case uint8:
    488 if av, ok := actual.(uint8); ok {
    489 notEqual = ev != av
    490 ok_ = true
    491 es, as = strconv.FormatUint(uint64(ev), 10), strconv.FormatUint(uint64(av), 10)
    492 }
    493 case uint16:
    494 if av, ok := actual.(uint16); ok {
    495 notEqual = ev != av
    496 ok_ = true
    497 es, as = strconv.FormatUint(uint64(ev), 10), strconv.FormatUint(uint64(av), 10)
    498 }
    499 case uint32:
    500 if av, ok := actual.(uint32); ok {
    501 notEqual = ev != av
    502 ok_ = true
    503 es, as = strconv.FormatUint(uint64(ev), 10), strconv.FormatUint(uint64(av), 10)
    504 }
    505 case uint64:
    506 if av, ok := actual.(uint64); ok {
    507 notEqual = ev != av
    508 ok_ = true
    509 es, as = strconv.FormatUint(ev, 10), strconv.FormatUint(av, 10)
    510 }
    511 case bool:
    512 if av, ok := actual.(bool); ok {
    513 notEqual = ev != av
    514 ok_ = true
    515 if ev {
    516 es, as = "true", "false"
    517 } else {
    518 es, as = "false", "true"
    519 }
    520 }
    521 case float32:
    522 if av, ok := actual.(float32); ok {
    523 notEqual = ev != av
    524 ok_ = true
    525 }
    526 case float64:
    527 if av, ok := actual.(float64); ok {
    528 notEqual = ev != av
    529 ok_ = true
    530 }
    531 default:
    532 return fail(t, msgs, "uassert.NotEqual: unsupported type")
    533 }
    534
    535 /*
    536 // XXX: implement stringer and other well known similar interfaces
    537 type stringer interface{ String() string }
    538 if ev, ok := expected.(stringer); ok {
    539 if av, ok := actual.(stringer); ok {
    540 notEqual = ev.String() != av.String()
    541 ok_ = true
    542 }
    543 }
    544 */
    545
    546 if !ok_ {
    547 return fail(t, msgs, "uassert.NotEqual: different types") // XXX: display the types
    548 }
    549 if !notEqual {
    550 return fail(t, msgs, "uassert.NotEqual: same type and same value\n\texpected: %s\n\tactual: %s", es, as)
    551 }
    552
    553 return true
    554}
    555
    556func isNumberEmpty(n any) (isNumber, isEmpty bool) {
    557 switch n := n.(type) {
    558 // NOTE: the cases are split individually, so that n becomes of the
    559 // asserted type; the type of '0' was correctly inferred and converted
    560 // to the corresponding type, int, int8, etc.
    561 case int:
    562 return true, n == 0
    563 case int8:
    564 return true, n == 0
    565 case int16:
    566 return true, n == 0
    567 case int32:
    568 return true, n == 0
    569 case int64:
    570 return true, n == 0
    571 case uint:
    572 return true, n == 0
    573 case uint8:
    574 return true, n == 0
    575 case uint16:
    576 return true, n == 0
    577 case uint32:
    578 return true, n == 0
    579 case uint64:
    580 return true, n == 0
    581 case float32:
    582 return true, n == 0
    583 case float64:
    584 return true, n == 0
    585 }
    586 return false, false
    587}
    588
    589func Empty(t TestingT, obj any, msgs ...string) bool {
    590 t.Helper()
    591
    592 isNumber, isEmpty := isNumberEmpty(obj)
    593 if isNumber {
    594 if !isEmpty {
    595 return fail(t, msgs, "uassert.Empty: not empty number: %d", obj)
    596 }
    597 } else {
    598 switch val := obj.(type) {
    599 case string:
    600 if val != "" {
    601 return fail(t, msgs, "uassert.Empty: not empty string: %s", val)
    602 }
    603 case address:
    604 var zeroAddr address
    605 if val != zeroAddr {
    606 return fail(t, msgs, "uassert.Empty: not empty address: %s", string(val))
    607 }
    608 default:
    609 return fail(t, msgs, "uassert.Empty: unsupported type")
    610 }
    611 }
    612 return true
    613}
    614
    615func NotEmpty(t TestingT, obj any, msgs ...string) bool {
    616 t.Helper()
    617 isNumber, isEmpty := isNumberEmpty(obj)
    618 if isNumber {
    619 if isEmpty {
    620 return fail(t, msgs, "uassert.NotEmpty: empty number: %d", obj)
    621 }
    622 } else {
    623 switch val := obj.(type) {
    624 case string:
    625 if val == "" {
    626 return fail(t, msgs, "uassert.NotEmpty: empty string: %s", val)
    627 }
    628 case address:
    629 var zeroAddr address
    630 if val == zeroAddr {
    631 return fail(t, msgs, "uassert.NotEmpty: empty address: %s", string(val))
    632 }
    633 default:
    634 return fail(t, msgs, "uassert.NotEmpty: unsupported type")
    635 }
    636 }
    637 return true
    638}
    639
    640// Nil asserts that the value is nil.
    641func Nil(t TestingT, value any, msgs ...string) bool {
    642 t.Helper()
    643 if value != nil {
    644 return fail(t, msgs, "should be nil")
    645 }
    646 return true
    647}
    648
    649// NotNil asserts that the value is not nil.
    650func NotNil(t TestingT, value any, msgs ...string) bool {
    651 t.Helper()
    652 if value == nil {
    653 return fail(t, msgs, "should not be nil")
    654 }
    655 return true
    656}
    657
    658// TypedNil asserts that the value is a typed-nil (nil pointer) value.
    659func TypedNil(t TestingT, value any, msgs ...string) bool {
    660 t.Helper()
    661 if value == nil {
    662 return fail(t, msgs, "should be typed-nil but got nil instead")
    663 }
    664 if !istypednil(value) {
    665 return fail(t, msgs, "should be typed-nil")
    666 }
    667 return true
    668}
    669
    670// NotTypedNil asserts that the value is not a typed-nil (nil pointer) value.
    671func NotTypedNil(t TestingT, value any, msgs ...string) bool {
    672 t.Helper()
    673 if istypednil(value) {
    674 return fail(t, msgs, "should not be typed-nil")
    675 }
    676 return true
    677}
    678