github.com/cockroachdb/errors@v1.11.1/errutil/message_test.go (about)

     1  // Copyright 2019 The Cockroach Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    12  // implied. See the License for the specific language governing
    13  // permissions and limitations under the License.
    14  
    15  package errutil_test
    16  
    17  import (
    18  	goErr "errors"
    19  	"fmt"
    20  	"regexp"
    21  	"strings"
    22  	"testing"
    23  
    24  	"github.com/cockroachdb/errors/errbase"
    25  	"github.com/cockroachdb/errors/errutil"
    26  	"github.com/cockroachdb/errors/testutils"
    27  )
    28  
    29  // TestFormat checks edge cases of the utilities in this package.
    30  // More tests are exercised in the "fmttests" package.
    31  func TestFormat(t *testing.T) {
    32  	tt := testutils.T{t}
    33  
    34  	testCases := []struct {
    35  		name          string
    36  		err           error
    37  		expFmtSimple  string
    38  		expFmtVerbose string
    39  	}{
    40  		{"newf-empty",
    41  			errutil.Newf(emptyString),
    42  			``, `
    43  
    44  (1) attached stack trace
    45    -- stack trace:
    46    | github.com/cockroachdb/errors/errutil_test.TestFormat
    47    | <tab><path>
    48    | testing.tRunner
    49    | <tab><path>
    50    | runtime.goexit
    51    | <tab><path>
    52  Wraps: (2)
    53  Error types: (1) *withstack.withStack (2) *errutil.leafError`,
    54  		},
    55  
    56  		{"newf-empty-arg",
    57  			errutil.Newf(emptyString, 123),
    58  			`%!(EXTRA int=123)`, `
    59  %!(EXTRA int=123)
    60  (1) attached stack trace
    61    -- stack trace:
    62    | github.com/cockroachdb/errors/errutil_test.TestFormat
    63    | <tab><path>
    64    | testing.tRunner
    65    | <tab><path>
    66    | runtime.goexit
    67    | <tab><path>
    68  Wraps: (2) %!(EXTRA int=123)
    69  Error types: (1) *withstack.withStack (2) *errutil.leafError`,
    70  		},
    71  
    72  		{"wrapf-empty",
    73  			errutil.Wrapf(goErr.New("woo"), emptyString),
    74  			`woo`, `
    75  woo
    76  (1) attached stack trace
    77    -- stack trace:
    78    | github.com/cockroachdb/errors/errutil_test.TestFormat
    79    | <tab><path>
    80    | testing.tRunner
    81    | <tab><path>
    82    | runtime.goexit
    83    | <tab><path>
    84  Wraps: (2) woo
    85  Error types: (1) *withstack.withStack (2) *errors.errorString`,
    86  		},
    87  
    88  		{"wrapf-empty-arg",
    89  			errutil.Wrapf(goErr.New("woo"), emptyString, 123),
    90  			`%!(EXTRA int=123): woo`, `
    91  %!(EXTRA int=123): woo
    92  (1) attached stack trace
    93    -- stack trace:
    94    | github.com/cockroachdb/errors/errutil_test.TestFormat
    95    | <tab><path>
    96    | testing.tRunner
    97    | <tab><path>
    98    | runtime.goexit
    99    | <tab><path>
   100  Wraps: (2) %!(EXTRA int=123)
   101  Wraps: (3) woo
   102  Error types: (1) *withstack.withStack (2) *errutil.withPrefix (3) *errors.errorString`,
   103  		},
   104  
   105  		{"assert + wrap",
   106  			errutil.NewAssertionErrorWithWrappedErrf(&werrFmt{goErr.New("woo"), "wuu"}, "waa: %s", "hello"),
   107  			`waa: hello: wuu: woo`, `
   108  waa: hello: wuu: woo
   109  (1) assertion failure
   110  Wraps: (2) attached stack trace
   111    -- stack trace:
   112    | github.com/cockroachdb/errors/errutil_test.TestFormat
   113    | <tab><path>
   114    | testing.tRunner
   115    | <tab><path>
   116    | runtime.goexit
   117    | <tab><path>
   118  Wraps: (3) waa: hello
   119  Wraps: (4) wuu: woo
   120    | -- cause hidden behind barrier
   121    | wuu: woo
   122    | (1) wuu
   123    |   | -- this is wuu's
   124    |   | multi-line payload
   125    | Wraps: (2) woo
   126    | Error types: (1) *errutil_test.werrFmt (2) *errors.errorString
   127  Error types: (1) *assert.withAssertionFailure (2) *withstack.withStack (3) *errutil.withPrefix (4) *barriers.barrierErr`,
   128  		},
   129  
   130  		{"assert + wrap empty",
   131  			errutil.NewAssertionErrorWithWrappedErrf(&werrFmt{goErr.New("woo"), "wuu"}, emptyString),
   132  			`wuu: woo`, `
   133  wuu: woo
   134  (1) assertion failure
   135  Wraps: (2) attached stack trace
   136    -- stack trace:
   137    | github.com/cockroachdb/errors/errutil_test.TestFormat
   138    | <tab><path>
   139    | testing.tRunner
   140    | <tab><path>
   141    | runtime.goexit
   142    | <tab><path>
   143  Wraps: (3) wuu: woo
   144    | -- cause hidden behind barrier
   145    | wuu: woo
   146    | (1) wuu
   147    |   | -- this is wuu's
   148    |   | multi-line payload
   149    | Wraps: (2) woo
   150    | Error types: (1) *errutil_test.werrFmt (2) *errors.errorString
   151  Error types: (1) *assert.withAssertionFailure (2) *withstack.withStack (3) *barriers.barrierErr`,
   152  		},
   153  
   154  		{"assert + wrap empty+arg",
   155  			errutil.NewAssertionErrorWithWrappedErrf(&werrFmt{goErr.New("woo"), "wuu"}, emptyString, 123),
   156  			`%!(EXTRA int=123): wuu: woo`, `
   157  %!(EXTRA int=123): wuu: woo
   158  (1) assertion failure
   159  Wraps: (2) attached stack trace
   160    -- stack trace:
   161    | github.com/cockroachdb/errors/errutil_test.TestFormat
   162    | <tab><path>
   163    | testing.tRunner
   164    | <tab><path>
   165    | runtime.goexit
   166    | <tab><path>
   167  Wraps: (3) %!(EXTRA int=123)
   168  Wraps: (4) wuu: woo
   169    | -- cause hidden behind barrier
   170    | wuu: woo
   171    | (1) wuu
   172    |   | -- this is wuu's
   173    |   | multi-line payload
   174    | Wraps: (2) woo
   175    | Error types: (1) *errutil_test.werrFmt (2) *errors.errorString
   176  Error types: (1) *assert.withAssertionFailure (2) *withstack.withStack (3) *errutil.withPrefix (4) *barriers.barrierErr`,
   177  		},
   178  	}
   179  
   180  	for _, test := range testCases {
   181  		tt.Run(test.name, func(tt testutils.T) {
   182  			err := test.err
   183  
   184  			// %s is simple formatting
   185  			tt.CheckStringEqual(fmt.Sprintf("%s", err), test.expFmtSimple)
   186  
   187  			// %v is simple formatting too, for compatibility with the past.
   188  			tt.CheckStringEqual(fmt.Sprintf("%v", err), test.expFmtSimple)
   189  
   190  			// %q is always like %s but quotes the result.
   191  			ref := fmt.Sprintf("%q", test.expFmtSimple)
   192  			tt.CheckStringEqual(fmt.Sprintf("%q", err), ref)
   193  
   194  			// %+v is the verbose mode.
   195  			refV := strings.TrimPrefix(test.expFmtVerbose, "\n")
   196  			spv := fmt.Sprintf("%+v", err)
   197  			spv = fileref.ReplaceAllString(spv, "<path>")
   198  			spv = strings.ReplaceAll(spv, "\t", "<tab>")
   199  			tt.CheckStringEqual(spv, refV)
   200  		})
   201  	}
   202  }
   203  
   204  var fileref = regexp.MustCompile(`([a-zA-Z0-9\._/@-]*\.(?:go|s):\d+)`)
   205  
   206  type werrFmt struct {
   207  	cause error
   208  	msg   string
   209  }
   210  
   211  var _ errbase.Formatter = (*werrFmt)(nil)
   212  
   213  func (e *werrFmt) Error() string                 { return fmt.Sprintf("%s: %v", e.msg, e.cause) }
   214  func (e *werrFmt) Unwrap() error                 { return e.cause }
   215  func (e *werrFmt) Format(s fmt.State, verb rune) { errbase.FormatError(e, s, verb) }
   216  func (e *werrFmt) FormatError(p errbase.Printer) error {
   217  	p.Print(e.msg)
   218  	if p.Detail() {
   219  		p.Printf("-- this is %s's\nmulti-line payload", e.msg)
   220  	}
   221  	return e.cause
   222  }
   223  
   224  var emptyString = ""