Skip to content
This repository was archived by the owner on Dec 1, 2021. It is now read-only.
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: pkg/errors
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: confetti-framework/errors
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
Able to merge. These branches can be automatically merged.

Commits on Oct 24, 2020

  1. confetti-framework/confetti#73 fork pkg

    Reindert Vetter committed Oct 24, 2020
    Copy the full SHA
    244fec3 View commit details
  2. confetti-framework/confetti#73 Add error WithLevel

    Reindert Vetter committed Oct 24, 2020
    Copy the full SHA
    6e4c0ea View commit details
  3. Copy the full SHA
    90d1239 View commit details

Commits on Oct 25, 2020

  1. confetti-framework/confetti#73 Add http status to response

    Reindert Vetter committed Oct 25, 2020
    Copy the full SHA
    9e9c03c View commit details

Commits on Oct 26, 2020

  1. confetti-framework/confetti#73 Use Unwrap instead of cause

    Reindert Vetter committed Oct 26, 2020
    Copy the full SHA
    7871b20 View commit details

Commits on Oct 27, 2020

  1. confetti-framework/confetti#73 document helpers Is and As

    Reindert Vetter committed Oct 27, 2020
    Copy the full SHA
    1b67b3d View commit details

Commits on Nov 16, 2020

  1. confetti-framework/confetti#73 fix conflict

    Reindert Vetter committed Nov 16, 2020
    Copy the full SHA
    ef1c0d1 View commit details

Commits on Nov 20, 2020

  1. confetti-framework/confetti#88 remove error from value

    Reindert Vetter committed Nov 20, 2020
    Copy the full SHA
    1748370 View commit details

Commits on Nov 30, 2020

  1. confetti-framework/confetti#88 send helpful information if request do…

    …es not contain content
    Reindert Vetter committed Nov 30, 2020
    Copy the full SHA
    ae8b36a View commit details

Commits on Dec 21, 2020

  1. confetti-framework/confetti#90 Rename repo to Confetti

    Reindert Vetter committed Dec 21, 2020
    Copy the full SHA
    7d663d3 View commit details

Commits on Dec 22, 2020

  1. confetti-framework/confetti#90 Rename repo to Confetti

    Reindert Vetter committed Dec 22, 2020
    Copy the full SHA
    3d2f086 View commit details

Commits on Jan 30, 2021

  1. Update README.md

    reindert-vetter authored Jan 30, 2021
    Copy the full SHA
    b51e231 View commit details
  2. Update README.md

    reindert-vetter authored Jan 30, 2021
    Copy the full SHA
    a2ab3a1 View commit details
  3. Update README.md

    reindert-vetter authored Jan 30, 2021
    Copy the full SHA
    762b551 View commit details

Commits on Jan 31, 2021

  1. confetti-framework/docs#13 link to confetti-framework.com

    Reindert Vetter committed Jan 31, 2021
    Copy the full SHA
    b0cce00 View commit details
  2. confetti-framework/docs#13 link to confetti-framework.com

    Reindert Vetter committed Jan 31, 2021
    Copy the full SHA
    7bdf211 View commit details

Commits on Mar 7, 2021

  1. Create go.yml

    reindert-vetter authored Mar 7, 2021
    Copy the full SHA
    152867c View commit details
  2. Copy the full SHA
    e9ed4eb View commit details
  3. cover cov in tests

    Reindert Vetter committed Mar 7, 2021
    Copy the full SHA
    7d095be View commit details
  4. Copy the full SHA
    4d1e7fc View commit details
  5. cover cov in tests

    Reindert Vetter committed Mar 7, 2021
    Copy the full SHA
    b8c172d View commit details
  6. cover cov in tests

    Reindert Vetter committed Mar 7, 2021
    Copy the full SHA
    18782eb View commit details
  7. cover cov in tests

    Reindert Vetter committed Mar 7, 2021
    Copy the full SHA
    8ee376b View commit details

Commits on Feb 28, 2022

  1. Copy the full SHA
    c6a8a67 View commit details
Showing with 642 additions and 355 deletions.
  1. +18 −0 .github/workflows/ci.yml
  2. +1 −1 .travis.yml
  3. +1 −1 Makefile
  4. +16 −20 README.md
  5. +1 −1 bench_test.go
  6. +158 −80 errors.go
  7. +241 −85 errors_test.go
  8. +35 −40 example_test.go
  9. +77 −77 format_test.go
  10. +8 −0 go.mod
  11. +15 −0 go.sum
  12. +6 −11 go113.go
  13. +3 −5 go113_test.go
  14. +2 −2 json_test.go
  15. +60 −32 stack_test.go
18 changes: 18 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Test and coverage

on: [push, pull_request]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 2
- uses: actions/setup-go@v2
with:
go-version: '1.15'
- name: Run coverage
run: go list ./... | grep -v errors/test | tr '\n' ',' | rev | cut -c2- | rev | { read allpackages; go test -race -coverprofile=coverage.txt -covermode=atomic -coverpkg=$allpackages ./...; }
- name: Upload coverage to Codecov
run: bash <(curl -s https://codecov.io/bash)
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
language: go
go_import_path: github.com/pkg/errors
go_import_path: github.com/confetti-framework/errors
go:
- 1.11.x
- 1.12.x
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PKGS := github.com/pkg/errors
PKGS := github.com/confetti-framework/errors
SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS))
GO := go

36 changes: 16 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge)
[![codecov](https://codecov.io/gh/confetti-framework/errors/branch/main/graph/badge.svg?token=8ANZG4V48V)](https://codecov.io/gh/confetti-framework/errors)

# Errors

Package errors provides simple error handling primitives.

`go get github.com/pkg/errors`
`go get github.com/confetti-framework/errors`

The traditional error handling idiom in Go is roughly akin to
```go
@@ -23,37 +25,31 @@ if err != nil {
```
## Retrieving the cause of an error

Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`.
Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the
error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any
error value which implements this interface can be inspected by `errors.Unwrap`.
```go
type causer interface {
Cause() error
Unwrap() error
}
```
`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example:

`errors.Unwrap` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be
the original cause. For example:
```go
switch err := errors.Cause(err).(type) {
switch err := errors.Unwrap(err).(type) {
case *MyError:
// handle specifically
default:
// unknown error
}
```

[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).

## Roadmap

With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows:

- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible)
- 1.0. Final release.
<<<<<<< HEAD
=======
[Read the package documentation for more information](https://godoc.org/github.com/confetti-framework/errors).

>>>>>>> 762b551bf121c3fb7483623472bf3090cafff8d7
## Contributing

Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports.

Before sending a PR, please discuss your change by raising an issue.

## License

BSD-2-Clause
2 changes: 1 addition & 1 deletion bench_test.go
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ func BenchmarkErrors(b *testing.B) {
{1000, true},
}
for _, r := range runs {
part := "pkg/errors"
part := "confetti-framework/errors"
if r.std {
part = "errors"
}
238 changes: 158 additions & 80 deletions errors.go
Original file line number Diff line number Diff line change
@@ -34,41 +34,41 @@
// to reverse the operation of errors.Wrap to retrieve the original error
// for inspection. Any error value which implements this interface
//
// type causer interface {
// Cause() error
// type unwrapper interface {
// Unwrap() error
// }
//
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
// the topmost error that does not implement causer, which is assumed to be
// can be inspected by errors.Unwrap. errors.Unwrap will recursively retrieve
// the topmost error that does not implement unwrapper, which is assumed to be
// the original cause. For example:
//
// switch err := errors.Cause(err).(type) {
// switch err := errors.Unwrap(err).(type) {
// case *MyError:
// // handle specifically
// default:
// // unknown error
// }
//
// Although the causer interface is not exported by this package, it is
// Although the unwrapper interface is not exported by this package, it is
// considered a part of its stable public interface.
//
// Formatted printing of errors
//
// All error values returned from this package implement fmt.Formatter and can
// be formatted by the fmt package. The following verbs are supported:
//
// %s print the error. If the error has a Cause it will be
// %s print the error. If the error has a Unwrap it will be
// printed recursively.
// %v see %s
// %+v extended format. Each Frame of the error's StackTrace will
// be printed in detail.
//
// Retrieving the stack trace of an error or wrapper
//
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
// New, errorf, Wrap, and Wrap record a stack trace at the point they are
// invoked. This information can be retrieved with the following interface:
//
// type stackTracer interface {
// type StackTracer interface {
// StackTrace() errors.StackTrace
// }
//
@@ -80,7 +80,7 @@
// the fmt.Formatter interface that can be used for printing information about
// the stack trace of this error. For example:
//
// if err, ok := err.(stackTracer); ok {
// if err, ok := err.(StackTracer); ok {
// for _, f := range err.StackTrace() {
// fmt.Printf("%+s:%d\n", f, f)
// }
@@ -94,24 +94,21 @@ package errors

import (
"fmt"
syslog "github.com/confetti-framework/syslog/log_level"
"io"
net "net/http"
)

// New returns an error with the supplied message.
// New returns an error with the supplied message and formats
// according to a format specifier and returns the string
// as a value that satisfies error.
// New also records the stack trace at the point it was called.
func New(message string) error {
return &fundamental{
msg: message,
stack: callers(),
func New(message string, args ...interface{}) *fundamental {
if len(args) > 0 {
message = fmt.Sprintf(message, args...)
}
}

// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
// Errorf also records the stack trace at the point it was called.
func Errorf(format string, args ...interface{}) error {
return &fundamental{
msg: fmt.Sprintf(format, args...),
msg: message,
stack: callers(),
}
}
@@ -122,7 +119,9 @@ type fundamental struct {
*stack
}

func (f *fundamental) Error() string { return f.msg }
func (f *fundamental) Error() string {
return f.msg
}

func (f *fundamental) Format(s fmt.State, verb rune) {
switch verb {
@@ -140,6 +139,84 @@ func (f *fundamental) Format(s fmt.State, verb rune) {
}
}

func (f *fundamental) StackTrace() StackTrace {
return f.stack.StackTrace()
}

func FindLevel(err error) (syslog.Level, bool) {
var level syslog.Level
var levelHolder *withLevel

if !As(err, &levelHolder) {
return level, false
}

return levelHolder.level, true
}

func WithLevel(err error, level syslog.Level) *withLevel {
if err == nil {
return nil
}
return &withLevel{
err,
level,
}
}

type withLevel struct {
cause error
level syslog.Level
}

func (w *withLevel) Error() string {
return w.cause.Error()
}

func (w *withLevel) Format(st fmt.State, verb rune) {
Format(st, verb, w.cause)
}

func (w *withLevel) Unwrap() error {
return w.cause
}

func FindStatus(err error) (int, bool) {
var statusHolder *withStatus

ok := As(err, &statusHolder)
if !ok {
return net.StatusInternalServerError, false
}

return statusHolder.status, true
}

func WithStatus(err error, status int) *withStatus {
if err == nil {
return nil
}
return &withStatus{
err,
status,
}
}

type withStatus struct {
cause error
status int
}

func (w *withStatus) Error() string {
return w.cause.Error()
}

func (w *withStatus) Format(st fmt.State, verb rune) {
Format(st, verb, w.cause)
}

func (w *withStatus) Unwrap() error { return w.cause }

// WithStack annotates err with a stack trace at the point WithStack was called.
// If err is nil, WithStack returns nil.
func WithStack(err error) error {
@@ -152,21 +229,26 @@ func WithStack(err error) error {
}
}

func FindStack(err error) (StackTrace, bool) {
var stackHolder interface{ StackTrace() StackTrace }

if !As(err, &stackHolder) {
return StackTrace{}, false
}

return stackHolder.StackTrace(), true
}

type withStack struct {
error
*stack
}

func (w *withStack) Cause() error { return w.error }

// Unwrap provides compatibility for Go 1.13 error chains.
func (w *withStack) Unwrap() error { return w.error }

func (w *withStack) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v", w.Cause())
fmt.Fprintf(s, "%+v", w.Unwrap())
w.stack.Format(s, verb)
return
}
@@ -178,33 +260,25 @@ func (w *withStack) Format(s fmt.State, verb rune) {
}
}

func (w *withStack) Unwrap() error { return w.error }

func (w *withStack) StackTrace() StackTrace {
return w.stack.StackTrace()
}

// Wrap returns an error annotating err with a stack trace
// at the point Wrap is called, and the supplied message.
// If err is nil, Wrap returns nil.
func Wrap(err error, message string) error {
func Wrap(err error, message string, args ...interface{}) *withStack {
if err == nil {
return nil
}
err = &withMessage{
cause: err,
msg: message,
}
return &withStack{
err,
callers(),
}
}

// Wrapf returns an error annotating err with a stack trace
// at the point Wrapf is called, and the format specifier.
// If err is nil, Wrapf returns nil.
func Wrapf(err error, format string, args ...interface{}) error {
if err == nil {
return nil
if len(args) > 0 {
message = fmt.Sprintf(message, args...)
}
err = &withMessage{
cause: err,
msg: fmt.Sprintf(format, args...),
msg: message,
}
return &withStack{
err,
@@ -213,45 +287,33 @@ func Wrapf(err error, format string, args ...interface{}) error {
}

// WithMessage annotates err with a new message.
// If err is nil, WithMessage returns nil.
func WithMessage(err error, message string) error {
if err == nil {
return nil
func WithMessage(err error, message string, args ...interface{}) *withMessage {
if len(args) > 0 {
message = fmt.Sprintf(message, args...)
}
return &withMessage{
cause: err,
msg: message,
}
}

// WithMessagef annotates err with the format specifier.
// If err is nil, WithMessagef returns nil.
func WithMessagef(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
return &withMessage{
cause: err,
msg: fmt.Sprintf(format, args...),
}
}

type withMessage struct {
cause error
msg string
}

func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
func (w *withMessage) Cause() error { return w.cause }

// Unwrap provides compatibility for Go 1.13 error chains.
func (w *withMessage) Unwrap() error { return w.cause }
func (w *withMessage) Error() string {
if w.cause == nil || w.cause.Error() == "" {
return w.msg
}
return w.msg + ": " + w.cause.Error()
}

func (w *withMessage) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v\n", w.Cause())
fmt.Fprintf(s, "%+v\n", w.Unwrap())
io.WriteString(s, w.msg)
return
}
@@ -261,28 +323,44 @@ func (w *withMessage) Format(s fmt.State, verb rune) {
}
}

// Cause returns the underlying cause of the error, if possible.
func (w *withMessage) Unwrap() error {
return w.cause
}

// Unwrap returns the underlying cause of the error, if possible.
// An error value has a cause if it implements the following
// interface:
//
// type causer interface {
// Cause() error
// type unwrapper interface {
// Unwrap() error
// }
//
// If the error does not implement Cause, the original error will
// If the error does not implement Unwrap, the original error will
// be returned. If the error is nil, nil will be returned without further
// investigation.
func Cause(err error) error {
type causer interface {
Cause() error
}

func Unwrap(err error) error {
for err != nil {
cause, ok := err.(causer)
unwrapper, ok := err.(unwrapper)
if !ok {
break
}
err = cause.Cause()
err = unwrapper.Unwrap()
}
return err
}

type unwrapper interface {
Unwrap() error
}

type StackTracer interface {
StackTrace() StackTrace
}

func Format(st fmt.State, verb rune, err error) {
if cause, ok := err.(interface{ Format(fmt.State, rune) }); ok {
cause.Format(st, verb)
} else {
io.WriteString(st, err.Error())
}
}
326 changes: 241 additions & 85 deletions errors_test.go

Large diffs are not rendered by default.

75 changes: 35 additions & 40 deletions example_test.go
Original file line number Diff line number Diff line change
@@ -2,8 +2,7 @@ package errors_test

import (
"fmt"

"github.com/pkg/errors"
"github.com/confetti-framework/errors"
)

func ExampleNew() {
@@ -19,16 +18,16 @@ func ExampleNew_printf() {

// Example output:
// whoops
// github.com/pkg/errors_test.ExampleNew_printf
// /home/dfc/src/github.com/pkg/errors/example_test.go:17
// github.com/confetti-framework/errors_test.ExampleNew_printf
// /home/dfc/src/github.com/confetti-framework/errors/example_test.go:17
// testing.runExample
// /home/dfc/go/src/testing/example.go:114
// testing.RunExamples
// /home/dfc/go/src/testing/example.go:38
// testing.(*M).Run
// /home/dfc/go/src/testing/testing.go:744
// main.main
// /github.com/pkg/errors/_test/_testmain.go:106
// /github.com/confetti-framework/errors/_test/_testmain.go:106
// runtime.main
// /home/dfc/go/src/runtime/proc.go:183
// runtime.goexit
@@ -58,30 +57,30 @@ func ExampleWithStack_printf() {

// Example Output:
// whoops
// github.com/pkg/errors_test.ExampleWithStack_printf
// /home/fabstu/go/src/github.com/pkg/errors/example_test.go:55
// github.com/confetti-framework/errors_test.ExampleWithStack_printf
// /home/fabstu/go/src/github.com/confetti-framework/errors/example_test.go:55
// testing.runExample
// /usr/lib/go/src/testing/example.go:114
// testing.RunExamples
// /usr/lib/go/src/testing/example.go:38
// testing.(*M).Run
// /usr/lib/go/src/testing/testing.go:744
// main.main
// github.com/pkg/errors/_test/_testmain.go:106
// github.com/confetti-framework/errors/_test/_testmain.go:106
// runtime.main
// /usr/lib/go/src/runtime/proc.go:183
// runtime.goexit
// /usr/lib/go/src/runtime/asm_amd64.s:2086
// github.com/pkg/errors_test.ExampleWithStack_printf
// /home/fabstu/go/src/github.com/pkg/errors/example_test.go:56
// github.com/confetti-framework/errors_test.ExampleWithStack_printf
// /home/fabstu/go/src/github.com/confetti-framework/errors/example_test.go:56
// testing.runExample
// /usr/lib/go/src/testing/example.go:114
// testing.RunExamples
// /usr/lib/go/src/testing/example.go:38
// testing.(*M).Run
// /usr/lib/go/src/testing/testing.go:744
// main.main
// github.com/pkg/errors/_test/_testmain.go:106
// github.com/confetti-framework/errors/_test/_testmain.go:106
// runtime.main
// /usr/lib/go/src/runtime/proc.go:183
// runtime.goexit
@@ -103,10 +102,10 @@ func fn() error {
return errors.Wrap(e3, "outer")
}

func ExampleCause() {
func ExampleUnwrap() {
err := fn()
fmt.Println(err)
fmt.Println(errors.Cause(err))
fmt.Println(errors.Unwrap(err))

// Output: outer: middle: inner: error
// error
@@ -118,66 +117,62 @@ func ExampleWrap_extended() {

// Example output:
// error
// github.com/pkg/errors_test.fn
// /home/dfc/src/github.com/pkg/errors/example_test.go:47
// github.com/pkg/errors_test.ExampleCause_printf
// /home/dfc/src/github.com/pkg/errors/example_test.go:63
// github.com/confetti-framework/errors_test.fn
// /home/dfc/src/github.com/confetti-framework/errors/example_test.go:47
// github.com/confetti-framework/errors_test.ExampleUnwrap_printf
// /home/dfc/src/github.com/confetti-framework/errors/example_test.go:63
// testing.runExample
// /home/dfc/go/src/testing/example.go:114
// testing.RunExamples
// /home/dfc/go/src/testing/example.go:38
// testing.(*M).Run
// /home/dfc/go/src/testing/testing.go:744
// main.main
// /github.com/pkg/errors/_test/_testmain.go:104
// /github.com/confetti-framework/errors/_test/_testmain.go:104
// runtime.main
// /home/dfc/go/src/runtime/proc.go:183
// runtime.goexit
// /home/dfc/go/src/runtime/asm_amd64.s:2059
// github.com/pkg/errors_test.fn
// /home/dfc/src/github.com/pkg/errors/example_test.go:48: inner
// github.com/pkg/errors_test.fn
// /home/dfc/src/github.com/pkg/errors/example_test.go:49: middle
// github.com/pkg/errors_test.fn
// /home/dfc/src/github.com/pkg/errors/example_test.go:50: outer
// github.com/confetti-framework/errors_test.fn
// /home/dfc/src/github.com/confetti-framework/errors/example_test.go:48: inner
// github.com/confetti-framework/errors_test.fn
// /home/dfc/src/github.com/confetti-framework/errors/example_test.go:49: middle
// github.com/confetti-framework/errors_test.fn
// /home/dfc/src/github.com/confetti-framework/errors/example_test.go:50: outer
}

func ExampleWrapf() {
func ExampleWrapFormat() {
cause := errors.New("whoops")
err := errors.Wrapf(cause, "oh noes #%d", 2)
err := errors.Wrap(cause, "oh noes #%d", 2)
fmt.Println(err)

// Output: oh noes #2: whoops
}

func ExampleErrorf_extended() {
err := errors.Errorf("whoops: %s", "foo")
err := errors.New("whoops: %s", "foo")
fmt.Printf("%+v", err)

// Example output:
// whoops: foo
// github.com/pkg/errors_test.ExampleErrorf
// /home/dfc/src/github.com/pkg/errors/example_test.go:101
// github.com/confetti-framework/errors_test.ExampleErrorf
// /home/dfc/src/github.com/confetti-framework/errors/example_test.go:101
// testing.runExample
// /home/dfc/go/src/testing/example.go:114
// testing.RunExamples
// /home/dfc/go/src/testing/example.go:38
// testing.(*M).Run
// /home/dfc/go/src/testing/testing.go:744
// main.main
// /github.com/pkg/errors/_test/_testmain.go:102
// /github.com/confetti-framework/errors/_test/_testmain.go:102
// runtime.main
// /home/dfc/go/src/runtime/proc.go:183
// runtime.goexit
// /home/dfc/go/src/runtime/asm_amd64.s:2059
}

func Example_stackTrace() {
type stackTracer interface {
StackTrace() errors.StackTrace
}

err, ok := errors.Cause(fn()).(stackTracer)
err, ok := errors.Unwrap(fn()).(errors.StackTracer)
if !ok {
panic("oops, err does not implement stackTracer")
}
@@ -186,13 +181,13 @@ func Example_stackTrace() {
fmt.Printf("%+v", st[0:2]) // top two frames

// Example output:
// github.com/pkg/errors_test.fn
// /home/dfc/src/github.com/pkg/errors/example_test.go:47
// github.com/pkg/errors_test.Example_stackTrace
// /home/dfc/src/github.com/pkg/errors/example_test.go:127
// github.com/confetti-framework/errors_test.fn
// /home/dfc/src/github.com/confetti-framework/errors/example_test.go:47
// github.com/confetti-framework/errors_test.Example_stackTrace
// /home/dfc/src/github.com/confetti-framework/errors/example_test.go:127
}

func ExampleCause_printf() {
func ExampleUnwrap_printf() {
err := errors.Wrap(func() error {
return func() error {
return errors.New("hello world")
154 changes: 77 additions & 77 deletions format_test.go
Original file line number Diff line number Diff line change
@@ -26,8 +26,8 @@ func TestFormatNew(t *testing.T) {
New("error"),
"%+v",
"error\n" +
"github.com/pkg/errors.TestFormatNew\n" +
"\t.+/github.com/pkg/errors/format_test.go:26",
"github.com/confetti-framework/errors.TestFormatNew\n" +
"\t.+errors/format_test.go:26",
}, {
New("error"),
"%q",
@@ -45,19 +45,19 @@ func TestFormatErrorf(t *testing.T) {
format string
want string
}{{
Errorf("%s", "error"),
New("%s", "error"),
"%s",
"error",
}, {
Errorf("%s", "error"),
New("%s", "error"),
"%v",
"error",
}, {
Errorf("%s", "error"),
New("%s", "error"),
"%+v",
"error\n" +
"github.com/pkg/errors.TestFormatErrorf\n" +
"\t.+/github.com/pkg/errors/format_test.go:56",
"github.com/confetti-framework/errors.TestFormatErrorf\n" +
"\t.+errors/format_test.go:56",
}}

for i, tt := range tests {
@@ -82,8 +82,8 @@ func TestFormatWrap(t *testing.T) {
Wrap(New("error"), "error2"),
"%+v",
"error\n" +
"github.com/pkg/errors.TestFormatWrap\n" +
"\t.+/github.com/pkg/errors/format_test.go:82",
"github.com/confetti-framework/errors.TestFormatWrap\n" +
"\t.+errors/format_test.go:82",
}, {
Wrap(io.EOF, "error"),
"%s",
@@ -97,15 +97,15 @@ func TestFormatWrap(t *testing.T) {
"%+v",
"EOF\n" +
"error\n" +
"github.com/pkg/errors.TestFormatWrap\n" +
"\t.+/github.com/pkg/errors/format_test.go:96",
"github.com/confetti-framework/errors.TestFormatWrap\n" +
"\t.+errors/format_test.go:96",
}, {
Wrap(Wrap(io.EOF, "error1"), "error2"),
"%+v",
"EOF\n" +
"error1\n" +
"github.com/pkg/errors.TestFormatWrap\n" +
"\t.+/github.com/pkg/errors/format_test.go:103\n",
"github.com/confetti-framework/errors.TestFormatWrap\n" +
"\t.+errors/format_test.go:103\n",
}, {
Wrap(New("error with space"), "context"),
"%q",
@@ -117,40 +117,40 @@ func TestFormatWrap(t *testing.T) {
}
}

func TestFormatWrapf(t *testing.T) {
func TestFormatWrapFormat(t *testing.T) {
tests := []struct {
error
format string
want string
}{{
Wrapf(io.EOF, "error%d", 2),
Wrap(io.EOF, "error%d", 2),
"%s",
"error2: EOF",
}, {
Wrapf(io.EOF, "error%d", 2),
Wrap(io.EOF, "error%d", 2),
"%v",
"error2: EOF",
}, {
Wrapf(io.EOF, "error%d", 2),
Wrap(io.EOF, "error%d", 2),
"%+v",
"EOF\n" +
"error2\n" +
"github.com/pkg/errors.TestFormatWrapf\n" +
"\t.+/github.com/pkg/errors/format_test.go:134",
"github.com/confetti-framework/errors.TestFormatWrap\n" +
"\t.+errors/format_test.go:134",
}, {
Wrapf(New("error"), "error%d", 2),
Wrap(New("error"), "error%d", 2),
"%s",
"error2: error",
}, {
Wrapf(New("error"), "error%d", 2),
Wrap(New("error"), "error%d", 2),
"%v",
"error2: error",
}, {
Wrapf(New("error"), "error%d", 2),
Wrap(New("error"), "error%d", 2),
"%+v",
"error\n" +
"github.com/pkg/errors.TestFormatWrapf\n" +
"\t.+/github.com/pkg/errors/format_test.go:149",
"github.com/confetti-framework/errors.TestFormatWrap\n" +
"\t.+errors/format_test.go:149",
}}

for i, tt := range tests {
@@ -175,8 +175,8 @@ func TestFormatWithStack(t *testing.T) {
WithStack(io.EOF),
"%+v",
[]string{"EOF",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:175"},
"github.com/confetti-framework/errors.TestFormatWithStack\n" +
"\t.+errors/format_test.go:175"},
}, {
WithStack(New("error")),
"%s",
@@ -189,37 +189,37 @@ func TestFormatWithStack(t *testing.T) {
WithStack(New("error")),
"%+v",
[]string{"error",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:189",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:189"},
"github.com/confetti-framework/errors.TestFormatWithStack\n" +
"\t.+errors/format_test.go:189",
"github.com/confetti-framework/errors.TestFormatWithStack\n" +
"\t.+errors/format_test.go:189"},
}, {
WithStack(WithStack(io.EOF)),
"%+v",
[]string{"EOF",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:197",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:197"},
"github.com/confetti-framework/errors.TestFormatWithStack\n" +
"\t.+errors/format_test.go:197",
"github.com/confetti-framework/errors.TestFormatWithStack\n" +
"\t.+errors/format_test.go:197"},
}, {
WithStack(WithStack(Wrapf(io.EOF, "message"))),
WithStack(WithStack(Wrap(io.EOF, "message"))),
"%+v",
[]string{"EOF",
"message",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:205",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:205",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:205"},
}, {
WithStack(Errorf("error%d", 1)),
"github.com/confetti-framework/errors.TestFormatWithStack\n" +
"\t.+errors/format_test.go:205",
"github.com/confetti-framework/errors.TestFormatWithStack\n" +
"\t.+errors/format_test.go:205",
"github.com/confetti-framework/errors.TestFormatWithStack\n" +
"\t.+errors/format_test.go:205"},
}, {
WithStack(New("error%d", 1)),
"%+v",
[]string{"error1",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:216",
"github.com/pkg/errors.TestFormatWithStack\n" +
"\t.+/github.com/pkg/errors/format_test.go:216"},
"github.com/confetti-framework/errors.TestFormatWithStack\n" +
"\t.+errors/format_test.go:216",
"github.com/confetti-framework/errors.TestFormatWithStack\n" +
"\t.+errors/format_test.go:216"},
}}

for i, tt := range tests {
@@ -245,8 +245,8 @@ func TestFormatWithMessage(t *testing.T) {
"%+v",
[]string{
"error",
"github.com/pkg/errors.TestFormatWithMessage\n" +
"\t.+/github.com/pkg/errors/format_test.go:244",
"github.com/confetti-framework/errors.TestFormatWithMessage\n" +
"\t.+errors/format_test.go:244",
"error2"},
}, {
WithMessage(io.EOF, "addition1"),
@@ -272,33 +272,33 @@ func TestFormatWithMessage(t *testing.T) {
Wrap(WithMessage(io.EOF, "error1"), "error2"),
"%+v",
[]string{"EOF", "error1", "error2",
"github.com/pkg/errors.TestFormatWithMessage\n" +
"\t.+/github.com/pkg/errors/format_test.go:272"},
"github.com/confetti-framework/errors.TestFormatWithMessage\n" +
"\t.+errors/format_test.go:272"},
}, {
WithMessage(Errorf("error%d", 1), "error2"),
WithMessage(New("error%d", 1), "error2"),
"%+v",
[]string{"error1",
"github.com/pkg/errors.TestFormatWithMessage\n" +
"\t.+/github.com/pkg/errors/format_test.go:278",
"github.com/confetti-framework/errors.TestFormatWithMessage\n" +
"\t.+errors/format_test.go:278",
"error2"},
}, {
WithMessage(WithStack(io.EOF), "error"),
"%+v",
[]string{
"EOF",
"github.com/pkg/errors.TestFormatWithMessage\n" +
"\t.+/github.com/pkg/errors/format_test.go:285",
"github.com/confetti-framework/errors.TestFormatWithMessage\n" +
"\t.+errors/format_test.go:285",
"error"},
}, {
WithMessage(Wrap(WithStack(io.EOF), "inside-error"), "outside-error"),
"%+v",
[]string{
"EOF",
"github.com/pkg/errors.TestFormatWithMessage\n" +
"\t.+/github.com/pkg/errors/format_test.go:293",
"github.com/confetti-framework/errors.TestFormatWithMessage\n" +
"\t.+errors/format_test.go:293",
"inside-error",
"github.com/pkg/errors.TestFormatWithMessage\n" +
"\t.+/github.com/pkg/errors/format_test.go:293",
"github.com/confetti-framework/errors.TestFormatWithMessage\n" +
"\t.+errors/format_test.go:293",
"outside-error"},
}}

@@ -314,12 +314,12 @@ func TestFormatGeneric(t *testing.T) {
}{
{New("new-error"), []string{
"new-error",
"github.com/pkg/errors.TestFormatGeneric\n" +
"\t.+/github.com/pkg/errors/format_test.go:315"},
}, {Errorf("errorf-error"), []string{
"github.com/confetti-framework/errors.TestFormatGeneric\n" +
"\t.+errors/format_test.go:315"},
}, {New("errorf-error"), []string{
"errorf-error",
"github.com/pkg/errors.TestFormatGeneric\n" +
"\t.+/github.com/pkg/errors/format_test.go:319"},
"github.com/confetti-framework/errors.TestFormatGeneric\n" +
"\t.+errors/format_test.go:319"},
}, {errors.New("errors-new-error"), []string{
"errors-new-error"},
},
@@ -332,22 +332,22 @@ func TestFormatGeneric(t *testing.T) {
}, {
func(err error) error { return WithStack(err) },
[]string{
"github.com/pkg/errors.(func·002|TestFormatGeneric.func2)\n\t" +
".+/github.com/pkg/errors/format_test.go:333",
"github.com/confetti-framework/errors.(func·002|TestFormatGeneric.func2)\n\t" +
".+errors/format_test.go:333",
},
}, {
func(err error) error { return Wrap(err, "wrap-error") },
[]string{
"wrap-error",
"github.com/pkg/errors.(func·003|TestFormatGeneric.func3)\n\t" +
".+/github.com/pkg/errors/format_test.go:339",
"github.com/confetti-framework/errors.(func·003|TestFormatGeneric.func3)\n\t" +
".+errors/format_test.go:339",
},
}, {
func(err error) error { return Wrapf(err, "wrapf-error%d", 1) },
func(err error) error { return Wrap(err, "wrap-error%d", 1) },
[]string{
"wrapf-error1",
"github.com/pkg/errors.(func·004|TestFormatGeneric.func4)\n\t" +
".+/github.com/pkg/errors/format_test.go:346",
"wrap-error1",
"github.com/confetti-framework/errors.(func·004|TestFormatGeneric.func4)\n\t" +
".+errors/format_test.go:346",
},
},
}
@@ -373,10 +373,10 @@ func TestFormatWrappedNew(t *testing.T) {
wrappedNew("error"),
"%+v",
"error\n" +
"github.com/pkg/errors.wrappedNew\n" +
"\t.+/github.com/pkg/errors/format_test.go:364\n" +
"github.com/pkg/errors.TestFormatWrappedNew\n" +
"\t.+/github.com/pkg/errors/format_test.go:373",
"github.com/confetti-framework/errors.wrappedNew\n" +
"\t.+errors/format_test.go:364\n" +
"github.com/confetti-framework/errors.TestFormatWrappedNew\n" +
"\t.+errors/format_test.go:373",
}}

for i, tt := range tests {
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module github.com/confetti-framework/errors

go 1.15

require (
github.com/confetti-framework/syslog v0.1.0-rc
github.com/stretchr/testify v1.6.1
)
15 changes: 15 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
github.com/confetti-framework/syslog v0.1.0-rc h1:BqzyW2p9uSxYOL1MQFrMGAcsix7X5nW8bgHlf7SuZkM=
github.com/confetti-framework/syslog v0.1.0-rc/go.mod h1:O6eT3y5cYDGQSVT6lrhScB5NKdylG0R304PmGiChm7Y=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
17 changes: 6 additions & 11 deletions go113.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
// +build go1.13

package errors

import (
stderrors "errors"
)

// Is reports whether any error in err's chain matches target.
// Is reports whether any error in err's chain matches any of the targets.
//
// The chain consists of err itself followed by the sequence of errors obtained by
// repeatedly calling Unwrap.
//
// An error is considered to match a target if it is equal to that target or if
// it implements a method Is(error) bool such that Is(target) returns true.
func Is(err, target error) bool { return stderrors.Is(err, target) }
func Is(err error, target error) bool {
return stderrors.Is(err, target)
}

// As finds the first error in err's chain that matches target, and if so, sets
// target to that error value and returns true.
@@ -28,11 +28,6 @@ func Is(err, target error) bool { return stderrors.Is(err, target) }
//
// As will panic if target is not a non-nil pointer to either a type that implements
// error, or to any interface type. As returns false if err is nil.
func As(err error, target interface{}) bool { return stderrors.As(err, target) }

// Unwrap returns the result of calling the Unwrap method on err, if err's
// type contains an Unwrap method returning error.
// Otherwise, Unwrap returns nil.
func Unwrap(err error) error {
return stderrors.Unwrap(err)
func As(err error, target interface{}) bool {
return stderrors.As(err, target)
}
8 changes: 3 additions & 5 deletions go113_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// +build go1.13

package errors

import (
@@ -48,7 +46,7 @@ func TestIs(t *testing.T) {
{
name: "with message format",
args: args{
err: WithMessagef(err, "%s", "test"),
err: WithMessage(err, "%s", "test"),
target: err,
},
want: true,
@@ -108,7 +106,7 @@ func TestAs(t *testing.T) {
{
name: "with message format",
args: args{
err: WithMessagef(err, "%s", "test"),
err: WithMessage(err, "%s", "test"),
target: new(customErr),
},
want: true,
@@ -159,7 +157,7 @@ func TestUnwrap(t *testing.T) {
},
{
name: "with message format",
args: args{err: WithMessagef(err, "%s", "test")},
args: args{err: WithMessage(err, "%s", "test")},
want: err,
},
{
4 changes: 2 additions & 2 deletions json_test.go
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ func TestFrameMarshalText(t *testing.T) {
want string
}{{
initpc,
`^github.com/pkg/errors\.init(\.ializers)? .+/github\.com/pkg/errors/stack_test.go:\d+$`,
`errors\.init(\.ializers)? .+/errors/stack_test.go:\d+$`,
}, {
0,
`^unknown$`,
@@ -34,7 +34,7 @@ func TestFrameMarshalJSON(t *testing.T) {
want string
}{{
initpc,
`^"github\.com/pkg/errors\.init(\.ializers)? .+/github\.com/pkg/errors/stack_test.go:\d+"$`,
`^"github\.com/confetti-framework/errors\.init(\.ializers)? .+errors/stack_test.go:\d+"$`,
}, {
0,
`^"unknown"$`,
92 changes: 60 additions & 32 deletions stack_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package errors

import (
stderrors "errors"
"fmt"
"github.com/confetti-framework/syslog/log_level"
"github.com/stretchr/testify/assert"
net "net/http"
"runtime"
"testing"
)
@@ -32,8 +36,8 @@ func TestFrameFormat(t *testing.T) {
}, {
initpc,
"%+s",
"github.com/pkg/errors.init\n" +
"\t.+/github.com/pkg/errors/stack_test.go",
"github.com/confetti-framework/errors.init\n" +
"\t.+/errors/stack_test.go",
}, {
0,
"%s",
@@ -45,7 +49,7 @@ func TestFrameFormat(t *testing.T) {
}, {
initpc,
"%d",
"9",
"13",
}, {
0,
"%d",
@@ -75,12 +79,12 @@ func TestFrameFormat(t *testing.T) {
}, {
initpc,
"%v",
"stack_test.go:9",
"stack_test.go:13",
}, {
initpc,
"%+v",
"github.com/pkg/errors.init\n" +
"\t.+/github.com/pkg/errors/stack_test.go:9",
"github.com/confetti-framework/errors.init\n" +
"\t.+/errors/stack_test.go:13",
}, {
0,
"%v",
@@ -98,7 +102,7 @@ func TestFuncname(t *testing.T) {
}{
{"", ""},
{"runtime.main", "main"},
{"github.com/pkg/errors.funcname", "funcname"},
{"github.com/confetti-framework/errors.funcname", "funcname"},
{"funcname", "funcname"},
{"io.copyBuffer", "copyBuffer"},
{"main.(*R).Write", "(*R).Write"},
@@ -119,38 +123,38 @@ func TestStackTrace(t *testing.T) {
want []string
}{{
New("ooh"), []string{
"github.com/pkg/errors.TestStackTrace\n" +
"\t.+/github.com/pkg/errors/stack_test.go:121",
"github.com/confetti-framework/errors.TestStackTrace\n" +
"\t.+/errors/stack_test.go:125",
},
}, {
Wrap(New("ooh"), "ahh"), []string{
"github.com/pkg/errors.TestStackTrace\n" +
"\t.+/github.com/pkg/errors/stack_test.go:126", // this is the stack of Wrap, not New
"github.com/confetti-framework/errors.TestStackTrace\n" +
"\t.+/errors/stack_test.go:130", // this is the stack of Wrap, not New
},
}, {
Cause(Wrap(New("ooh"), "ahh")), []string{
"github.com/pkg/errors.TestStackTrace\n" +
"\t.+/github.com/pkg/errors/stack_test.go:131", // this is the stack of New
Unwrap(Wrap(New("ooh"), "ahh")), []string{
"github.com/confetti-framework/errors.TestStackTrace\n" +
"\t.+/errors/stack_test.go:135", // this is the stack of New
},
}, {
func() error { return New("ooh") }(), []string{
`github.com/pkg/errors.TestStackTrace.func1` +
"\n\t.+/github.com/pkg/errors/stack_test.go:136", // this is the stack of New
"github.com/pkg/errors.TestStackTrace\n" +
"\t.+/github.com/pkg/errors/stack_test.go:136", // this is the stack of New's caller
`github.com/confetti-framework/errors.TestStackTrace.func1` +
"\n\t.+/errors/stack_test.go:140", // this is the stack of New
"github.com/confetti-framework/errors.TestStackTrace\n" +
"\t.+/errors/stack_test.go:140", // this is the stack of New's caller
},
}, {
Cause(func() error {
Unwrap(func() error {
return func() error {
return Errorf("hello %s", fmt.Sprintf("world: %s", "ooh"))
return New("hello %s", fmt.Sprintf("world: %s", "ooh"))
}()
}()), []string{
`github.com/pkg/errors.TestStackTrace.func2.1` +
"\n\t.+/github.com/pkg/errors/stack_test.go:145", // this is the stack of Errorf
`github.com/pkg/errors.TestStackTrace.func2` +
"\n\t.+/github.com/pkg/errors/stack_test.go:146", // this is the stack of Errorf's caller
"github.com/pkg/errors.TestStackTrace\n" +
"\t.+/github.com/pkg/errors/stack_test.go:147", // this is the stack of Errorf's caller's caller
`github.com/confetti-framework/errors.TestStackTrace.func2.1` +
"\n\t.+/errors/stack_test.go:149", // this is the stack of New
`github.com/confetti-framework/errors.TestStackTrace.func2` +
"\n\t.+/errors/stack_test.go:150", // this is the stack of New's caller
"github.com/confetti-framework/errors.TestStackTrace\n" +
"\t.+/errors/stack_test.go:151", // this is the stack of New's caller's caller
},
}}
for i, tt := range tests {
@@ -220,26 +224,50 @@ func TestStackTraceFormat(t *testing.T) {
}, {
stackTrace()[:2],
"%v",
`\[stack_test.go:174 stack_test.go:221\]`,
`\[stack_test.go:178 stack_test.go:225\]`,
}, {
stackTrace()[:2],
"%+v",
"\n" +
"github.com/pkg/errors.stackTrace\n" +
"\t.+/github.com/pkg/errors/stack_test.go:174\n" +
"github.com/pkg/errors.TestStackTraceFormat\n" +
"\t.+/github.com/pkg/errors/stack_test.go:225",
"github.com/confetti-framework/errors.stackTrace\n" +
"\t.+/errors/stack_test.go:178\n" +
"github.com/confetti-framework/errors.TestStackTraceFormat\n" +
"\t.+/errors/stack_test.go:229",
}, {
stackTrace()[:2],
"%#v",
`\[\]errors.Frame{stack_test.go:174, stack_test.go:233}`,
`\[\]errors.Frame{stack_test.go:178, stack_test.go:237}`,
}}

for i, tt := range tests {
testFormatRegexp(t, i, tt.StackTrace, tt.format, tt.want)
}
}

func TestGetStackTraceFromStatusErr(t *testing.T) {
err := New("message").Status(net.StatusNotFound)
result := fmt.Sprintf("%+v", err)
assert.Contains(t, result, "stack_test.go")
}

func TestGetStackTraceFromLevelErr(t *testing.T) {
err := New("message").Level(log_level.ALERT)
result := fmt.Sprintf("%+v", err)
assert.Contains(t, result, "stack_test.go")
}

func TestGetStackTraceFromSimpleErr(t *testing.T) {
err := WithStatus(stderrors.New("message"), net.StatusNotFound)
result := fmt.Sprintf("%+v", err)
assert.Equal(t, "message", result)
}

func TestGetStackTraceByWithMethod(t *testing.T) {
err := WithStatus(stderrors.New("message"), net.StatusNotFound)
result := fmt.Sprintf("%+v", err)
assert.Equal(t, "message", result)
}

// a version of runtime.Caller that returns a Frame, not a uintptr.
func caller() Frame {
var pcs [3]uintptr