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 = ""