2025-01-21 21:16:54 -03:00
|
|
|
// Copyright (c) 2025 Gustavo "Guz" L. de Mello
|
|
|
|
|
// Copyright (c) 2025 The Lored.dev Contributors
|
|
|
|
|
//
|
|
|
|
|
// Contents of this file, expect as otherwise noted, are dual-licensed under the
|
|
|
|
|
// Apache License, Version 2.0 <http://www.apache.org/licenses/LICENSE-2.0> or
|
|
|
|
|
// the MIT license <http://opensource.org/licenses/MIT>, at you option.
|
|
|
|
|
//
|
|
|
|
|
// You may use this file in compliance with the licenses.
|
|
|
|
|
//
|
|
|
|
|
// Unless required by applicable law or agreed to in writing, this file distributed
|
|
|
|
|
// under the licenses is distributed on as "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
|
|
|
|
|
// OF ANY KIND, either express or implied.
|
|
|
|
|
//
|
2025-02-26 19:07:25 -03:00
|
|
|
// An original copy of this file can be found at http://forge.capytal.company/loreddev/x/tinyssert/tinyssert.go.
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:34:52 -03:00
|
|
|
// Package tinyssert is a minimal set of assertions functions for testing and simulation
|
|
|
|
|
// testing, all in one file.
|
2025-01-21 21:16:54 -03:00
|
|
|
//
|
|
|
|
|
// The most simple way of using the package is importing it directly and using the
|
|
|
|
|
// alias functions:
|
|
|
|
|
//
|
|
|
|
|
// package main
|
|
|
|
|
//
|
|
|
|
|
// import (
|
|
|
|
|
// "log"
|
2025-01-22 16:21:00 -03:00
|
|
|
// "forge.capytal.company/loreddev/x/tinyssert"
|
2025-01-21 21:16:54 -03:00
|
|
|
// )
|
|
|
|
|
//
|
|
|
|
|
// func main() {
|
|
|
|
|
// expected := "value"
|
|
|
|
|
// value := "value"
|
2025-01-22 16:21:00 -03:00
|
|
|
// log.Println(tinyssert.Equal(expected, value)) // "true"
|
2025-01-21 21:16:54 -03:00
|
|
|
// }
|
|
|
|
|
//
|
2025-05-14 11:32:08 -03:00
|
|
|
// You can create your own "assert" variable and have more control
|
|
|
|
|
// over how asserts work, see the [New] constructor for more information:
|
2025-01-21 21:16:54 -03:00
|
|
|
//
|
|
|
|
|
// package main
|
|
|
|
|
//
|
|
|
|
|
// import (
|
|
|
|
|
// "log/slog"
|
2025-01-22 16:21:00 -03:00
|
|
|
// "forge.capytal.company/loreddev/x/tinyssert"
|
2025-01-21 21:16:54 -03:00
|
|
|
// )
|
|
|
|
|
//
|
|
|
|
|
// var logger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{}))
|
2025-05-14 11:32:08 -03:00
|
|
|
// var assert = tinyssert.NewAssertions(tinyssert.WithLogger(logger))
|
2025-01-21 21:16:54 -03:00
|
|
|
//
|
|
|
|
|
// func main() {
|
|
|
|
|
// expected := "value"
|
|
|
|
|
// value := "not value"
|
|
|
|
|
// assert.Equal(expected, value) // "expected \"value\", got \"not value\"" with the call stack and returns false
|
|
|
|
|
// }
|
2025-05-14 11:33:34 -03:00
|
|
|
//
|
|
|
|
|
// Preferably, when using assertions inside production code or libraries, you can use
|
|
|
|
|
// the assertions via dependency injection. This provides a easy way to disable
|
|
|
|
|
// assertions in production (see [NewDisabled]) while being able to test an API without
|
|
|
|
|
// changing it:
|
|
|
|
|
//
|
|
|
|
|
// package main
|
|
|
|
|
//
|
|
|
|
|
// import (
|
|
|
|
|
// "flag"
|
|
|
|
|
// "log/slog"
|
|
|
|
|
//
|
|
|
|
|
// "forge.capytal.company/loreddev/x/tinyssert"
|
|
|
|
|
// )
|
|
|
|
|
//
|
|
|
|
|
// var debug = flag.Bool("debug", false, "Run the application in debug mode")
|
|
|
|
|
//
|
|
|
|
|
// func init() {
|
|
|
|
|
// flag.Parse()
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// func main() {
|
|
|
|
|
// logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{}))
|
|
|
|
|
// assert := tinyssert.NewDisabled()
|
|
|
|
|
// if *debug {
|
|
|
|
|
// assert := tinyssert.New(tinyssert.WithLogger(logger))
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// app := App{logger: logger, assert: assert}
|
|
|
|
|
//
|
|
|
|
|
// app.Start()
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// type App struct {
|
|
|
|
|
// logger: *slog.Logger
|
|
|
|
|
// assert: tinyssert.Assertions
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// function (app *App) Start() {
|
|
|
|
|
// app.assert.OK(app.logger, "Logger must be initialized before the application")
|
|
|
|
|
//
|
|
|
|
|
// // ...
|
|
|
|
|
// }
|
2025-01-22 16:21:00 -03:00
|
|
|
package tinyssert
|
2025-01-21 21:16:54 -03:00
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"log/slog"
|
|
|
|
|
"os"
|
|
|
|
|
"path"
|
|
|
|
|
"reflect"
|
|
|
|
|
"runtime"
|
|
|
|
|
"strings"
|
|
|
|
|
"unicode"
|
|
|
|
|
"unicode/utf8"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Assertions represents all the API provided by the [assert] package. Implementation
|
|
|
|
|
// of this interface can have extra logic on their state such as panicking or using
|
|
|
|
|
// [testing.T.FailNow] to halt the program from continuing on failed assertions instead
|
|
|
|
|
// of just return false.
|
2025-05-14 11:30:42 -03:00
|
|
|
//
|
|
|
|
|
// `msg` argument(s) is(/are) optional, the first argument should always be a string.
|
|
|
|
|
// The string can have formatting verbs, with the remaining arguments being used to fill
|
|
|
|
|
// those verbs. So for example:
|
|
|
|
|
//
|
|
|
|
|
// if argument > 0 {
|
|
|
|
|
// tinyssert.OK(value, "Since %d is greater than 0, this should always be ok", argument)
|
|
|
|
|
// }
|
2025-01-21 21:16:54 -03:00
|
|
|
type Assertions interface {
|
2025-05-14 11:32:08 -03:00
|
|
|
// Asserts that the value is not zero-valued, is nil, or panics, aka. "is ok".
|
2025-07-30 19:18:28 -03:00
|
|
|
Ok(v any, msg ...any)
|
2025-01-21 21:16:54 -03:00
|
|
|
|
|
|
|
|
// Asserts that the actual value is equal to the expected value.
|
2025-07-30 19:18:28 -03:00
|
|
|
Equal(expected, actual any, msg ...any)
|
2025-01-21 21:16:54 -03:00
|
|
|
// Asserts that the actual value is not equal to the expected value.
|
2025-07-30 19:18:28 -03:00
|
|
|
NotEqual(notExpected, actual any, msg ...any)
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
// Asserts that the value is nil.
|
2025-07-30 19:18:28 -03:00
|
|
|
Nil(v any, msg ...any)
|
2025-05-14 11:32:08 -03:00
|
|
|
// Asserts that the value is not nil.
|
2025-07-30 19:18:28 -03:00
|
|
|
NotNil(v any, msg ...any)
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
// Asserts that the value is a boolean true.
|
2025-07-30 19:18:28 -03:00
|
|
|
True(b bool, msg ...any)
|
2025-05-14 11:32:08 -03:00
|
|
|
// Asserts that the value is a boolean false.
|
2025-07-30 19:18:28 -03:00
|
|
|
False(b bool, msg ...any)
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
// Asserts that the value is zero-valued.
|
2025-07-30 19:18:28 -03:00
|
|
|
Zero(v any, msg ...any)
|
2025-05-14 11:32:08 -03:00
|
|
|
// Asserts that the value is not zero-valued.
|
2025-07-30 19:18:28 -03:00
|
|
|
NotZero(v any, msg ...any)
|
2025-01-21 21:16:54 -03:00
|
|
|
|
|
|
|
|
// Asserts that the function panics.
|
2025-07-30 19:18:28 -03:00
|
|
|
Panic(fn func(), msg ...any)
|
2025-01-21 21:16:54 -03:00
|
|
|
// Asserts that the function does not panics.
|
2025-07-30 19:18:28 -03:00
|
|
|
NotPanic(fn func(), msg ...any)
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
// Logs the formatted failure message and/or marks the test as failed if possible,
|
|
|
|
|
// depending of what is possible to the implementation.
|
|
|
|
|
Fail(f Failure)
|
|
|
|
|
// Panics with the formatted failure message and/or marks the test as failed,
|
|
|
|
|
// depending of what is possible to the implementation.
|
|
|
|
|
FailNow(f Failure)
|
2025-01-21 21:16:54 -03:00
|
|
|
|
|
|
|
|
// Gets the caller stack.
|
|
|
|
|
CallerInfo() []string
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
// AssertionsErr is the same as [Assertions], but it returns [Failure] on it's method, useful
|
|
|
|
|
// for assertions that can also be returned as errors.
|
|
|
|
|
type AssertionsErr interface {
|
|
|
|
|
Assertions
|
|
|
|
|
|
|
|
|
|
// Asserts that the value is not zero-valued, is nil, or panics, aka. "is ok".
|
|
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
OkErr(v any, msg ...any) Failure
|
|
|
|
|
|
|
|
|
|
// Asserts that the actual value is equal to the expected value.
|
|
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
EqualErr(expected, actual any, msg ...any) Failure
|
|
|
|
|
// Asserts that the actual value is not equal to the expected value.
|
|
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
NotEqualErr(notExpected, actual any, msg ...any) Failure
|
|
|
|
|
|
|
|
|
|
// Asserts that the value is nil.
|
|
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
NilErr(v any, msg ...any) Failure
|
|
|
|
|
// Asserts that the value is not nil.
|
|
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
NotNilErr(v any, msg ...any) Failure
|
|
|
|
|
|
|
|
|
|
// Asserts that the value is a boolean true.
|
|
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
TrueErr(b bool, msg ...any) Failure
|
|
|
|
|
// Asserts that the value is a boolean false.
|
|
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
FalseErr(b bool, msg ...any) Failure
|
|
|
|
|
|
|
|
|
|
// Asserts that the value is zero-valued.
|
|
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
ZeroErr(v any, msg ...any) Failure
|
|
|
|
|
// Asserts that the value is not zero-valued.
|
|
|
|
|
NotZeroErr(v any, msg ...any) Failure
|
|
|
|
|
|
|
|
|
|
// Asserts that the function panics.
|
|
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
PanicErr(fn func(), msg ...any) Failure
|
|
|
|
|
// Asserts that the function does not panics.
|
|
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
NotPanicErr(fn func(), msg ...any) Failure
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:45:45 -03:00
|
|
|
// New constructs a new implementation of [Assertions]. Use `opts` to customize the behaviour
|
|
|
|
|
// of the implementation.
|
2025-07-30 19:18:28 -03:00
|
|
|
func New(opts ...Option) AssertionsErr {
|
2025-05-14 11:32:08 -03:00
|
|
|
a := &assertions{
|
|
|
|
|
panic: false,
|
|
|
|
|
log: slog.New(slog.NewTextHandler(io.Discard, &slog.HandlerOptions{})),
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
test: nil,
|
|
|
|
|
helper: nil,
|
|
|
|
|
}
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
for _, opt := range opts {
|
|
|
|
|
opt(a)
|
|
|
|
|
}
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
if th, ok := a.test.(helperT); ok {
|
|
|
|
|
a.helper = th
|
|
|
|
|
}
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
return a
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:46:00 -03:00
|
|
|
// Option is used in new constructor functions (such as [New] and [NewDisabled]) to customize
|
|
|
|
|
// the behaviour of the implementation.
|
2025-05-14 11:32:08 -03:00
|
|
|
type Option = func(*assertions)
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:46:00 -03:00
|
|
|
// WithPanic sets the implementation to panic when an assertion fails. If used together with
|
|
|
|
|
// [WithTest], the implementation should use [testing.T.FailNow] instead of panic.
|
2025-05-14 11:32:08 -03:00
|
|
|
func WithPanic() Option {
|
|
|
|
|
return func(a *assertions) {
|
|
|
|
|
a.panic = true
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
}
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:46:00 -03:00
|
|
|
// WithTest provides a [TestingT] implementation, such as the provided by the [testing] stadard package
|
|
|
|
|
// to be used to log and mark tests as failed if possible.
|
|
|
|
|
//
|
|
|
|
|
// If the implementation has an Errorf method, it will be used instead of any logger provided by [WithLogger].
|
|
|
|
|
//
|
|
|
|
|
// If the implementation has an FailNow method, it will be used instead of panic.
|
2025-05-14 11:32:08 -03:00
|
|
|
func WithTest(t TestingT) Option {
|
|
|
|
|
return func(a *assertions) {
|
|
|
|
|
a.test = t
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
}
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:46:00 -03:00
|
|
|
// WithLogger provides an [slog.Logger] instance to be used by the [Assertions] implementation to log
|
|
|
|
|
// failed assertions.
|
|
|
|
|
//
|
|
|
|
|
// If used together with [WithTest], the logger is not used if the [TestingT] implementation provided has
|
|
|
|
|
// an Errorf method.
|
2025-05-14 11:32:08 -03:00
|
|
|
func WithLogger(l *slog.Logger) Option {
|
|
|
|
|
return func(a *assertions) {
|
|
|
|
|
a.log = l
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
}
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
type assertions struct {
|
|
|
|
|
panic bool
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
test TestingT
|
|
|
|
|
helper helperT
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
log *slog.Logger
|
|
|
|
|
group string
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:46:00 -03:00
|
|
|
// TestingT is a wrapper interface around [testing.T].
|
2025-01-21 21:16:54 -03:00
|
|
|
type TestingT interface {
|
|
|
|
|
Errorf(format string, args ...any)
|
|
|
|
|
}
|
|
|
|
|
type helperT interface {
|
|
|
|
|
Helper()
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
var _ Assertions = (*assertions)(nil)
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) EqualErr(expected, actual any, msg ...any) Failure {
|
2025-05-14 11:32:08 -03:00
|
|
|
if a.equal(expected, actual) {
|
|
|
|
|
return nil
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
return a.fail(fmt.Sprintf("expected %v (right), got %v (left)", expected, actual), msg...)
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) Equal(expected, actual any, msg ...any) {
|
|
|
|
|
_ = a.EqualErr(expected, actual, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a *assertions) NotEqualErr(notExpected, actual any, msg ...any) Failure {
|
2025-05-14 11:32:08 -03:00
|
|
|
if !a.equal(notExpected, actual) {
|
|
|
|
|
return nil
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
return a.fail(fmt.Sprintf("expected to %v (right) and %v (left) to be not-equal", notExpected, actual), msg...)
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) NotEqual(notExpected, actual any, msg ...any) {
|
|
|
|
|
_ = a.NotEqualErr(notExpected, actual, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
func (a *assertions) equal(ex, ac any) bool {
|
2025-07-30 19:18:28 -03:00
|
|
|
if nex, nac := a.OkErr(ex), a.OkErr(ac); (nex != nil) != (nac != nil) {
|
2025-05-14 11:32:08 -03:00
|
|
|
return false
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
if reflect.DeepEqual(ex, ac) {
|
2025-01-21 21:16:54 -03:00
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
ev, av := reflect.ValueOf(ex), reflect.ValueOf(ac)
|
2025-01-21 21:16:54 -03:00
|
|
|
|
|
|
|
|
if ev == av {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if av.Type().ConvertibleTo(ev.Type()) {
|
2025-05-14 11:32:08 -03:00
|
|
|
return reflect.DeepEqual(ex, av.Convert(ev.Type()).Interface())
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
if fmt.Sprintf("%#v", ex) == fmt.Sprintf("%#v", ac) {
|
2025-01-21 21:16:54 -03:00
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) OkErr(v any, msg ...any) Failure {
|
2025-05-14 11:32:08 -03:00
|
|
|
if a.nil(v) {
|
|
|
|
|
return a.fail("expected not-nil value", msg...)
|
|
|
|
|
}
|
|
|
|
|
if a.zero(v) {
|
|
|
|
|
return a.fail("expected non-zero value", msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if f, ok := v.(func()); ok {
|
|
|
|
|
if a.panics(f) {
|
|
|
|
|
return a.fail("expected to not panic")
|
|
|
|
|
}
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
|
|
|
|
|
return nil
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) Ok(v any, msg ...any) {
|
|
|
|
|
_ = a.OkErr(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a *assertions) NilErr(v any, msg ...any) Failure {
|
2025-05-14 11:32:08 -03:00
|
|
|
if a.nil(v) {
|
|
|
|
|
return nil
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
return a.fail("expected nil value", msg...)
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) Nil(v any, msg ...any) {
|
|
|
|
|
_ = a.NilErr(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a *assertions) NotNilErr(v any, msg ...any) Failure {
|
2025-05-14 11:32:08 -03:00
|
|
|
if !a.nil(v) {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
return a.fail("expected not-nil value", msg...)
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) NotNil(v any, msg ...any) {
|
|
|
|
|
_ = a.NotNilErr(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
func (a *assertions) nil(v any) bool {
|
|
|
|
|
if v == nil {
|
2025-01-21 21:16:54 -03:00
|
|
|
return true
|
|
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
|
|
|
|
|
rv := reflect.ValueOf(v)
|
|
|
|
|
rk := rv.Kind()
|
|
|
|
|
if rk >= reflect.Chan && rk <= reflect.Slice && rv.IsNil() {
|
2025-01-21 21:16:54 -03:00
|
|
|
return true
|
|
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
|
2025-01-21 21:16:54 -03:00
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) TrueErr(v bool, msg ...any) Failure {
|
2025-05-14 11:32:08 -03:00
|
|
|
if v {
|
|
|
|
|
return nil
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
return a.fail("expected true", msg...)
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) True(v bool, msg ...any) {
|
|
|
|
|
_ = a.TrueErr(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a *assertions) FalseErr(v bool, msg ...any) Failure {
|
2025-05-14 11:32:08 -03:00
|
|
|
if !v {
|
|
|
|
|
return nil
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
return a.fail("expected false", msg...)
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) False(v bool, msg ...any) {
|
|
|
|
|
_ = a.FalseErr(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a *assertions) ZeroErr(v any, msg ...any) Failure {
|
2025-05-14 11:32:08 -03:00
|
|
|
if a.zero(v) {
|
|
|
|
|
return nil
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
return a.fail("expected zero value", msg...)
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) Zero(v any, msg ...any) {
|
|
|
|
|
_ = a.ZeroErr(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a *assertions) NotZeroErr(v any, msg ...any) Failure {
|
2025-05-14 11:32:08 -03:00
|
|
|
if !a.zero(v) {
|
|
|
|
|
return nil
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
return a.fail("expected non-zero value", msg...)
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) NotZero(v any, msg ...any) {
|
|
|
|
|
_ = a.NotZeroErr(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
func (a *assertions) zero(v any) bool {
|
|
|
|
|
if v != nil && !reflect.DeepEqual(v, reflect.Zero(reflect.TypeOf(v)).Interface()) {
|
2025-01-21 21:16:54 -03:00
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) PanicErr(fn func(), msg ...any) Failure {
|
2025-05-14 11:32:08 -03:00
|
|
|
if a.panics(fn) {
|
|
|
|
|
return nil
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
return a.fail("expected function to panic", msg...)
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) Panic(fn func(), msg ...any) {
|
|
|
|
|
_ = a.PanicErr(fn, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a *assertions) NotPanicErr(fn func(), msg ...any) Failure {
|
2025-05-14 11:32:08 -03:00
|
|
|
if !a.panics(fn) {
|
|
|
|
|
return nil
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
return a.fail("expected function to not panic", msg...)
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) NotPanic(fn func(), msg ...any) {
|
|
|
|
|
_ = a.NotPanicErr(fn, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
func (a *assertions) panics(fn func()) bool {
|
2025-01-21 21:16:54 -03:00
|
|
|
var r any
|
|
|
|
|
func() {
|
|
|
|
|
defer func() {
|
|
|
|
|
r = recover()
|
|
|
|
|
}()
|
|
|
|
|
fn()
|
|
|
|
|
}()
|
|
|
|
|
return r != nil
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (a *assertions) fail(reason string, msg ...any) Failure {
|
2025-05-14 11:32:08 -03:00
|
|
|
if a.helper != nil {
|
|
|
|
|
a.helper.Helper()
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
f := failure{
|
|
|
|
|
reason: reason,
|
|
|
|
|
message: fmtMessage(msg),
|
|
|
|
|
callerInfo: a.CallerInfo(),
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
if n, ok := a.test.(interface {
|
2025-01-21 21:16:54 -03:00
|
|
|
Name() string
|
|
|
|
|
}); ok {
|
2025-07-30 19:18:28 -03:00
|
|
|
f.test = n.Name()
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
if a.panic {
|
|
|
|
|
a.FailNow(f)
|
|
|
|
|
} else {
|
|
|
|
|
a.Fail(f)
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
return f
|
|
|
|
|
}
|
2025-01-21 21:16:54 -03:00
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
func (a *assertions) Fail(f Failure) {
|
|
|
|
|
if ft, ok := a.test.(interface {
|
|
|
|
|
Fail()
|
|
|
|
|
}); ok {
|
|
|
|
|
a.test.Errorf("ASSERTION FAILED:\n%s", f.String())
|
|
|
|
|
ft.Fail()
|
2025-01-21 21:16:54 -03:00
|
|
|
} else {
|
2025-05-14 11:32:08 -03:00
|
|
|
a.log.Error("ASSERTION FAILED",
|
2025-07-30 19:18:28 -03:00
|
|
|
slog.String("reason", f.Reason()),
|
|
|
|
|
slog.String("message", f.Message()),
|
|
|
|
|
slog.String("test", f.Test()),
|
|
|
|
|
slog.Any("caller", f.CallerInfo()),
|
2025-05-14 11:32:08 -03:00
|
|
|
)
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
func (a *assertions) FailNow(f Failure) {
|
|
|
|
|
if ft, ok := a.test.(interface {
|
|
|
|
|
FailNow()
|
|
|
|
|
}); ok {
|
|
|
|
|
a.test.Errorf("ASSERTION FAILED:\n%s", f.String())
|
|
|
|
|
ft.FailNow()
|
|
|
|
|
} else {
|
|
|
|
|
panic(f.String())
|
2025-01-21 21:16:54 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
func fmtMessage(msg ...any) string {
|
2025-01-21 21:16:54 -03:00
|
|
|
switch len(msg) {
|
|
|
|
|
case 0:
|
|
|
|
|
return ""
|
|
|
|
|
case 1:
|
|
|
|
|
if s, ok := msg[0].(string); ok {
|
|
|
|
|
return s
|
|
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
return fmt.Sprintf("%v", msg[0])
|
2025-01-21 21:16:54 -03:00
|
|
|
default:
|
|
|
|
|
var m string
|
|
|
|
|
if s, ok := msg[0].(string); ok {
|
|
|
|
|
m = s
|
|
|
|
|
} else {
|
|
|
|
|
m = fmt.Sprintf("%v", msg[0])
|
|
|
|
|
}
|
|
|
|
|
return fmt.Sprintf(m, msg[1:]...)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (as *assertions) CallerInfo() []string {
|
|
|
|
|
callers := []string{}
|
|
|
|
|
for i := 0; ; i++ {
|
|
|
|
|
pc, file, line, ok := runtime.Caller(i)
|
|
|
|
|
if !ok {
|
|
|
|
|
// We reached the end of the call stack
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Edge case found in https://github.com/stretchr/testify/issues/180
|
|
|
|
|
if file == "<autogenerated>" {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
f := runtime.FuncForPC(pc)
|
|
|
|
|
if f == nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
name := f.Name()
|
|
|
|
|
|
|
|
|
|
if name == "testing.Runner" {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
filename := path.Base(file)
|
|
|
|
|
dirname := path.Base(path.Dir(file))
|
|
|
|
|
if (dirname != "assert" && dirname != "mock" && dirname != "require") ||
|
|
|
|
|
filename == "mock_test.go" {
|
|
|
|
|
callers = append(callers, fmt.Sprintf("%s:%d", file, line))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Remove the package
|
|
|
|
|
s := strings.Split(name, ".")
|
|
|
|
|
name = s[len(s)-1]
|
|
|
|
|
|
|
|
|
|
if isTest(name, "Test") || isTest(name, "Benchmark") || isTest(name, "Example") {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return callers
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isTest(name, prefix string) bool {
|
|
|
|
|
if !strings.HasPrefix(name, prefix) {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
if len(name) == len(prefix) {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
r, _ := utf8.DecodeRuneInString(name[len(prefix):])
|
|
|
|
|
return !unicode.IsLower(r)
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
type failure struct {
|
|
|
|
|
reason string
|
|
|
|
|
message string
|
2025-05-14 11:32:08 -03:00
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
test string
|
|
|
|
|
callerInfo []string
|
2025-05-14 11:32:08 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
var _ Failure = failure{}
|
|
|
|
|
|
|
|
|
|
func (e failure) Reason() string {
|
|
|
|
|
return e.reason
|
|
|
|
|
}
|
2025-05-14 11:32:08 -03:00
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (e failure) Message() string {
|
|
|
|
|
return e.message
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e failure) Error() string {
|
|
|
|
|
if e.message != "" {
|
|
|
|
|
return fmt.Sprintf("assertion failed, %s: %s", e.reason, e.message)
|
2025-05-14 11:32:08 -03:00
|
|
|
}
|
2025-07-30 19:18:28 -03:00
|
|
|
return fmt.Sprintf("assertion failed, %s", e.reason)
|
2025-05-14 11:32:08 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (e failure) String() string {
|
2025-05-14 11:32:08 -03:00
|
|
|
c := map[string]string{
|
2025-07-30 19:18:28 -03:00
|
|
|
"Reason": e.reason,
|
2025-05-14 11:32:08 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
if e.message != "" {
|
|
|
|
|
c["Message"] = e.message
|
2025-05-14 11:32:08 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
if e.test != "" {
|
|
|
|
|
c["Test"] = e.test
|
2025-05-14 11:32:08 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c["Stack Trace"] = e.StackTrace()
|
|
|
|
|
|
|
|
|
|
var out string
|
|
|
|
|
for k, m := range c {
|
|
|
|
|
var s string
|
|
|
|
|
for _, l := range strings.Split(m, "\n") {
|
|
|
|
|
s += fmt.Sprintf("\t%s\n", l)
|
|
|
|
|
}
|
|
|
|
|
out += fmt.Sprintf("\t%s:\n%s", k, s)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return out
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:28 -03:00
|
|
|
func (e failure) Test() string {
|
|
|
|
|
return e.test
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (e failure) CallerInfo() []string {
|
|
|
|
|
return e.callerInfo
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-14 11:32:08 -03:00
|
|
|
// StackTrace returns the CallerInfo strings as a formatted stack trace.
|
2025-07-30 19:18:28 -03:00
|
|
|
func (e failure) StackTrace() string {
|
|
|
|
|
return strings.Join(e.callerInfo, "\n\t")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Failure interface {
|
|
|
|
|
Reason() string
|
|
|
|
|
Message() string
|
|
|
|
|
Test() string
|
|
|
|
|
StackTrace() string
|
|
|
|
|
CallerInfo() []string
|
|
|
|
|
|
|
|
|
|
error
|
|
|
|
|
fmt.Stringer
|
2025-05-14 11:32:08 -03:00
|
|
|
}
|
|
|
|
|
|
2025-01-21 21:16:54 -03:00
|
|
|
type disabledAssertions struct{}
|
|
|
|
|
|
2025-05-14 11:32:32 -03:00
|
|
|
// NewDisabled creates a new implementation of Assertions that always a nil error and
|
|
|
|
|
// never panics or marks the test as failed, with the exception of Fail, FailNow and
|
|
|
|
|
// CallerInfo, which uses their corresponding [Fail], [FailNow] and [CallerInfo] top-level
|
|
|
|
|
// functions.
|
|
|
|
|
//
|
|
|
|
|
// The `opts` argument does nothing, and is just available to make the function signature
|
|
|
|
|
// equal to [New].
|
2025-07-30 19:18:28 -03:00
|
|
|
func NewDisabled(opts ...Option) AssertionsErr {
|
2025-05-14 11:32:32 -03:00
|
|
|
_ = opts
|
2025-02-26 19:20:19 -03:00
|
|
|
return &disabledAssertions{}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:30 -03:00
|
|
|
func (*disabledAssertions) Ok(any, ...any) {}
|
|
|
|
|
func (*disabledAssertions) Equal(_, _ any, _ ...any) {}
|
|
|
|
|
func (*disabledAssertions) NotEqual(_, _ any, _ ...any) {}
|
|
|
|
|
func (*disabledAssertions) Nil(any, ...any) {}
|
|
|
|
|
func (*disabledAssertions) NotNil(any, ...any) {}
|
|
|
|
|
func (*disabledAssertions) True(bool, ...any) {}
|
|
|
|
|
func (*disabledAssertions) False(bool, ...any) {}
|
|
|
|
|
func (*disabledAssertions) Zero(any, ...any) {}
|
|
|
|
|
func (*disabledAssertions) NotZero(any, ...any) {}
|
|
|
|
|
func (*disabledAssertions) Panic(func(), ...any) {}
|
|
|
|
|
func (*disabledAssertions) NotPanic(func(), ...any) {}
|
2025-07-30 19:18:28 -03:00
|
|
|
func (*disabledAssertions) OkErr(any, ...any) Failure { return nil }
|
|
|
|
|
func (*disabledAssertions) EqualErr(_, _ any, _ ...any) Failure { return nil }
|
|
|
|
|
func (*disabledAssertions) NotEqualErr(_, _ any, _ ...any) Failure { return nil }
|
|
|
|
|
func (*disabledAssertions) NilErr(any, ...any) Failure { return nil }
|
|
|
|
|
func (*disabledAssertions) NotNilErr(any, ...any) Failure { return nil }
|
|
|
|
|
func (*disabledAssertions) TrueErr(bool, ...any) Failure { return nil }
|
|
|
|
|
func (*disabledAssertions) FalseErr(bool, ...any) Failure { return nil }
|
|
|
|
|
func (*disabledAssertions) ZeroErr(any, ...any) Failure { return nil }
|
|
|
|
|
func (*disabledAssertions) NotZeroErr(any, ...any) Failure { return nil }
|
|
|
|
|
func (*disabledAssertions) PanicErr(func(), ...any) Failure { return nil }
|
|
|
|
|
func (*disabledAssertions) NotPanicErr(func(), ...any) Failure { return nil }
|
|
|
|
|
func (*disabledAssertions) Fail(f Failure) { Default.Fail(f) }
|
|
|
|
|
func (*disabledAssertions) FailNow(f Failure) { Default.FailNow(f) }
|
|
|
|
|
func (*disabledAssertions) CallerInfo() []string { return Default.CallerInfo() }
|
2025-05-14 11:33:10 -03:00
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
// DefaultLogger is the default [slog.Logger] used by [Default]
|
|
|
|
|
DefaultLogger = slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{}))
|
|
|
|
|
|
|
|
|
|
// Default implementation of [Assertions] used by the top-level API functions.
|
|
|
|
|
Default = New(WithLogger(DefaultLogger))
|
|
|
|
|
)
|
|
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// Ok asserts that the value is not zero-valued, is nil, or panics, aka. "is ok".
|
2025-05-14 11:33:10 -03:00
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
2025-07-30 19:18:28 -03:00
|
|
|
func Ok(obj any, msg ...any) {
|
|
|
|
|
Default.Ok(obj, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// OkErr asserts that the value is not zero-valued, is nil, or panics, aka. "is ok".
|
2025-07-30 19:18:28 -03:00
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
|
|
|
|
func OkErr(obj any, msg ...any) Failure {
|
|
|
|
|
return Default.OkErr(obj, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Equal asserts that the actual value is equal to the expected value.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
|
|
|
|
func Equal(expected, actual any, msg ...any) {
|
|
|
|
|
Default.Equal(expected, actual, msg...)
|
2025-05-14 11:33:10 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// EqualErr asserts that the actual value is equal to the expected value.
|
2025-07-30 19:18:28 -03:00
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
|
|
|
|
func EqualErr(expected, actual any, msg ...any) Failure {
|
|
|
|
|
return Default.EqualErr(expected, actual, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NotEqual asserts that the actual value is not equal to the expected value.
|
2025-05-14 11:33:10 -03:00
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
2025-07-30 19:18:28 -03:00
|
|
|
func NotEqual(notExpected, actual any, msg ...any) {
|
|
|
|
|
Default.NotEqual(notExpected, actual, msg...)
|
2025-05-14 11:33:10 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// NotEqualErr asserts that the actual value is not equal to the expected value.
|
2025-07-30 19:18:28 -03:00
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
2025-05-14 11:33:10 -03:00
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
2025-07-30 19:18:28 -03:00
|
|
|
func NotEqualErr(notExpected, actual any, msg ...any) Failure {
|
|
|
|
|
return Default.NotEqualErr(notExpected, actual, msg...)
|
2025-05-14 11:33:10 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Nil asserts that the value is nil.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
2025-07-30 19:18:28 -03:00
|
|
|
func Nil(v any, msg ...any) {
|
|
|
|
|
Default.Nil(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// NilErr asserts that the value is nil.
|
2025-07-30 19:18:28 -03:00
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
|
|
|
|
func NilErr(v any, msg ...any) Failure {
|
|
|
|
|
return Default.NilErr(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NotNil asserts that the value is not nil.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
|
|
|
|
func NotNil(v any, msg ...any) {
|
|
|
|
|
Default.NotNil(v, msg...)
|
2025-05-14 11:33:10 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// NotNilErr asserts that the value is not nil.
|
2025-07-30 19:18:28 -03:00
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
|
|
|
|
func NotNilErr(v any, msg ...any) Failure {
|
|
|
|
|
return Default.NotNilErr(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// True asserts that the value is a boolean true.
|
2025-05-14 11:33:10 -03:00
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
2025-07-30 19:18:28 -03:00
|
|
|
func True(v bool, msg ...any) {
|
|
|
|
|
Default.True(v, msg...)
|
2025-05-14 11:33:10 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// TrueErr asserts that the value is a boolean true.
|
2025-07-30 19:18:28 -03:00
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
2025-05-14 11:33:10 -03:00
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
2025-07-30 19:18:28 -03:00
|
|
|
func TrueErr(v bool, msg ...any) Failure {
|
|
|
|
|
return Default.TrueErr(v, msg...)
|
2025-05-14 11:33:10 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// False asserts that the value is a boolean false.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
2025-07-30 19:18:28 -03:00
|
|
|
func False(v bool, msg ...any) {
|
|
|
|
|
Default.False(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// FalseErr asserts that the value is a boolean false.
|
2025-07-30 19:18:28 -03:00
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
|
|
|
|
func FalseErr(v bool, msg ...any) Failure {
|
|
|
|
|
return Default.FalseErr(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Zero asserts that the value is zero-valued.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
|
|
|
|
func Zero(v any, msg ...any) {
|
|
|
|
|
Default.Zero(v, msg...)
|
2025-05-14 11:33:10 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// ZeroErr asserts that the value is zero-valued.
|
2025-07-30 19:18:28 -03:00
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
|
|
|
|
func ZeroErr(v any, msg ...any) Failure {
|
|
|
|
|
return Default.ZeroErr(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NotZero asserts that the value is not zero-valued.
|
2025-05-14 11:33:10 -03:00
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
2025-07-30 19:18:28 -03:00
|
|
|
func NotZero(v any, msg ...any) {
|
|
|
|
|
Default.NotZero(v, msg...)
|
2025-05-14 11:33:10 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// NotZeroErr asserts that the value is not zero-valued.
|
2025-07-30 19:18:28 -03:00
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
|
|
|
|
func NotZeroErr(v any, msg ...any) Failure {
|
|
|
|
|
return Default.NotZeroErr(v, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Panic asserts that the function panics.
|
2025-05-14 11:33:10 -03:00
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
2025-07-30 19:18:28 -03:00
|
|
|
func Panic(fn func(), msg ...any) {
|
|
|
|
|
Default.Panic(fn, msg...)
|
2025-05-14 11:33:10 -03:00
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// PanicErr asserts that the function panics.
|
2025-07-30 19:18:28 -03:00
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
2025-05-14 11:33:10 -03:00
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
2025-07-30 19:18:28 -03:00
|
|
|
func PanicErr(fn func(), msg ...any) Failure {
|
|
|
|
|
return Default.PanicErr(fn, msg...)
|
2025-05-14 11:33:10 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NotPanic asserts that the function does not panics.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
2025-07-30 19:18:28 -03:00
|
|
|
func NotPanic(fn func(), msg ...any) {
|
|
|
|
|
Default.NotPanic(fn, msg...)
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// NotPanicErr asserts that the function does not panics.
|
2025-07-30 19:18:28 -03:00
|
|
|
// Returns a Failure if the assertion fails, otherwise returns nil.
|
|
|
|
|
//
|
|
|
|
|
// Logs the failure message with [DefaultLogger].
|
|
|
|
|
func NotPanicErr(fn func(), msg ...any) Failure {
|
|
|
|
|
return Default.NotPanicErr(fn, msg...)
|
2025-05-14 11:33:10 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fail logs the formatted failure message using [DefaultLogger].
|
|
|
|
|
func Fail(f Failure) {
|
|
|
|
|
Default.Fail(f)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FailNow panics with the formatted failure message.
|
|
|
|
|
func FailNow(f Failure) {
|
|
|
|
|
Default.FailNow(f)
|
|
|
|
|
}
|
2025-07-30 19:18:28 -03:00
|
|
|
|
2025-07-30 19:18:33 -03:00
|
|
|
// CallerInfo gets the caller stack.
|
2025-07-30 19:18:28 -03:00
|
|
|
func CallerInfo() []string {
|
|
|
|
|
return Default.CallerInfo()
|
|
|
|
|
}
|