.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / xerrors@v0.0.0-20200804184101-5ec99f83aff1 / fmt_test.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1/fmt_test.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1/fmt_test.go
new file mode 100644 (file)
index 0000000..1e3c060
--- /dev/null
@@ -0,0 +1,602 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package xerrors_test
+
+import (
+       "fmt"
+       "io"
+       "os"
+       "path"
+       "reflect"
+       "regexp"
+       "strconv"
+       "strings"
+       "testing"
+
+       "golang.org/x/xerrors"
+)
+
+func TestErrorf(t *testing.T) {
+       chained := &wrapped{"chained", nil}
+       chain := func(s ...string) (a []string) {
+               for _, s := range s {
+                       a = append(a, cleanPath(s))
+               }
+               return a
+       }
+       testCases := []struct {
+               got  error
+               want []string
+       }{{
+               xerrors.Errorf("no args"),
+               chain("no args/path.TestErrorf/path.go:xxx"),
+       }, {
+               xerrors.Errorf("no args: %s"),
+               chain("no args: %!s(MISSING)/path.TestErrorf/path.go:xxx"),
+       }, {
+               xerrors.Errorf("nounwrap: %s", "simple"),
+               chain(`nounwrap: simple/path.TestErrorf/path.go:xxx`),
+       }, {
+               xerrors.Errorf("nounwrap: %v", "simple"),
+               chain(`nounwrap: simple/path.TestErrorf/path.go:xxx`),
+       }, {
+               xerrors.Errorf("%s failed: %v", "foo", chained),
+               chain("foo failed/path.TestErrorf/path.go:xxx",
+                       "chained/somefile.go:xxx"),
+       }, {
+               xerrors.Errorf("no wrap: %s", chained),
+               chain("no wrap/path.TestErrorf/path.go:xxx",
+                       "chained/somefile.go:xxx"),
+       }, {
+               xerrors.Errorf("%s failed: %w", "foo", chained),
+               chain("wraps:foo failed/path.TestErrorf/path.go:xxx",
+                       "chained/somefile.go:xxx"),
+       }, {
+               xerrors.Errorf("nowrapv: %v", chained),
+               chain("nowrapv/path.TestErrorf/path.go:xxx",
+                       "chained/somefile.go:xxx"),
+       }, {
+               xerrors.Errorf("wrapw: %w", chained),
+               chain("wraps:wrapw/path.TestErrorf/path.go:xxx",
+                       "chained/somefile.go:xxx"),
+       }, {
+               xerrors.Errorf("wrapw %w middle", chained),
+               chain("wraps:wrapw chained middle/path.TestErrorf/path.go:xxx",
+                       "chained/somefile.go:xxx"),
+       }, {
+               xerrors.Errorf("not wrapped: %+v", chained),
+               chain("not wrapped: chained: somefile.go:123/path.TestErrorf/path.go:xxx"),
+       }}
+       for i, tc := range testCases {
+               t.Run(strconv.Itoa(i)+"/"+path.Join(tc.want...), func(t *testing.T) {
+                       got := errToParts(tc.got)
+                       if !reflect.DeepEqual(got, tc.want) {
+                               t.Errorf("Format:\n got: %#v\nwant: %#v", got, tc.want)
+                       }
+
+                       gotStr := tc.got.Error()
+                       wantStr := fmt.Sprint(tc.got)
+                       if gotStr != wantStr {
+                               t.Errorf("Error:\n got: %#v\nwant: %#v", got, tc.want)
+                       }
+               })
+       }
+}
+
+func TestErrorFormatter(t *testing.T) {
+       var (
+               simple   = &wrapped{"simple", nil}
+               elephant = &wrapped{
+                       "can't adumbrate elephant",
+                       detailed{},
+               }
+               nonascii = &wrapped{"café", nil}
+               newline  = &wrapped{"msg with\nnewline",
+                       &wrapped{"and another\none", nil}}
+               fallback  = &wrapped{"fallback", os.ErrNotExist}
+               oldAndNew = &wrapped{"new style", formatError("old style")}
+               framed    = &withFrameAndMore{
+                       frame: xerrors.Caller(0),
+               }
+               opaque = &wrapped{"outer",
+                       xerrors.Opaque(&wrapped{"mid",
+                               &wrapped{"inner", nil}})}
+       )
+       testCases := []struct {
+               err    error
+               fmt    string
+               want   string
+               regexp bool
+       }{{
+               err:  simple,
+               fmt:  "%s",
+               want: "simple",
+       }, {
+               err:  elephant,
+               fmt:  "%s",
+               want: "can't adumbrate elephant: out of peanuts",
+       }, {
+               err:  &wrapped{"a", &wrapped{"b", &wrapped{"c", nil}}},
+               fmt:  "%s",
+               want: "a: b: c",
+       }, {
+               err: simple,
+               fmt: "%+v",
+               want: "simple:" +
+                       "\n    somefile.go:123",
+       }, {
+               err: elephant,
+               fmt: "%+v",
+               want: "can't adumbrate elephant:" +
+                       "\n    somefile.go:123" +
+                       "\n  - out of peanuts:" +
+                       "\n    the elephant is on strike" +
+                       "\n    and the 12 monkeys" +
+                       "\n    are laughing",
+       }, {
+               err:  &oneNewline{nil},
+               fmt:  "%+v",
+               want: "123",
+       }, {
+               err: &oneNewline{&oneNewline{nil}},
+               fmt: "%+v",
+               want: "123:" +
+                       "\n  - 123",
+       }, {
+               err:  &newlineAtEnd{nil},
+               fmt:  "%+v",
+               want: "newlineAtEnd:\n    detail",
+       }, {
+               err: &newlineAtEnd{&newlineAtEnd{nil}},
+               fmt: "%+v",
+               want: "newlineAtEnd:" +
+                       "\n    detail" +
+                       "\n  - newlineAtEnd:" +
+                       "\n    detail",
+       }, {
+               err: framed,
+               fmt: "%+v",
+               want: "something:" +
+                       "\n    golang.org/x/xerrors_test.TestErrorFormatter" +
+                       "\n        .+/fmt_test.go:101" +
+                       "\n    something more",
+               regexp: true,
+       }, {
+               err:  fmtTwice("Hello World!"),
+               fmt:  "%#v",
+               want: "2 times Hello World!",
+       }, {
+               err:  fallback,
+               fmt:  "%s",
+               want: "fallback: file does not exist",
+       }, {
+               err: fallback,
+               fmt: "%+v",
+               // Note: no colon after the last error, as there are no details.
+               want: "fallback:" +
+                       "\n    somefile.go:123" +
+                       "\n  - file does not exist",
+       }, {
+               err:  opaque,
+               fmt:  "%s",
+               want: "outer: mid: inner",
+       }, {
+               err: opaque,
+               fmt: "%+v",
+               want: "outer:" +
+                       "\n    somefile.go:123" +
+                       "\n  - mid:" +
+                       "\n    somefile.go:123" +
+                       "\n  - inner:" +
+                       "\n    somefile.go:123",
+       }, {
+               err:  oldAndNew,
+               fmt:  "%v",
+               want: "new style: old style",
+       }, {
+               err:  oldAndNew,
+               fmt:  "%q",
+               want: `"new style: old style"`,
+       }, {
+               err: oldAndNew,
+               fmt: "%+v",
+               // Note the extra indentation.
+               // Colon for old style error is rendered by the fmt.Formatter
+               // implementation of the old-style error.
+               want: "new style:" +
+                       "\n    somefile.go:123" +
+                       "\n  - old style:" +
+                       "\n    otherfile.go:456",
+       }, {
+               err:  simple,
+               fmt:  "%-12s",
+               want: "simple      ",
+       }, {
+               // Don't use formatting flags for detailed view.
+               err: simple,
+               fmt: "%+12v",
+               want: "simple:" +
+                       "\n    somefile.go:123",
+       }, {
+               err:  elephant,
+               fmt:  "%+50s",
+               want: "          can't adumbrate elephant: out of peanuts",
+       }, {
+               err:  nonascii,
+               fmt:  "%q",
+               want: `"café"`,
+       }, {
+               err:  nonascii,
+               fmt:  "%+q",
+               want: `"caf\u00e9"`,
+       }, {
+               err:  simple,
+               fmt:  "% x",
+               want: "73 69 6d 70 6c 65",
+       }, {
+               err: newline,
+               fmt: "%s",
+               want: "msg with" +
+                       "\nnewline: and another" +
+                       "\none",
+       }, {
+               err: newline,
+               fmt: "%+v",
+               want: "msg with" +
+                       "\n    newline:" +
+                       "\n    somefile.go:123" +
+                       "\n  - and another" +
+                       "\n    one:" +
+                       "\n    somefile.go:123",
+       }, {
+               err: &wrapped{"", &wrapped{"inner message", nil}},
+               fmt: "%+v",
+               want: "somefile.go:123" +
+                       "\n  - inner message:" +
+                       "\n    somefile.go:123",
+       }, {
+               err:  spurious(""),
+               fmt:  "%s",
+               want: "spurious",
+       }, {
+               err:  spurious(""),
+               fmt:  "%+v",
+               want: "spurious",
+       }, {
+               err:  spurious("extra"),
+               fmt:  "%s",
+               want: "spurious",
+       }, {
+               err: spurious("extra"),
+               fmt: "%+v",
+               want: "spurious:\n" +
+                       "    extra",
+       }, {
+               err:  nil,
+               fmt:  "%+v",
+               want: "<nil>",
+       }, {
+               err:  (*wrapped)(nil),
+               fmt:  "%+v",
+               want: "<nil>",
+       }, {
+               err:  simple,
+               fmt:  "%T",
+               want: "*xerrors_test.wrapped",
+       }, {
+               err:  simple,
+               fmt:  "%🤪",
+               want: "%!🤪(*xerrors_test.wrapped)",
+               // For 1.13:
+               //  want: "%!🤪(*xerrors_test.wrapped=&{simple <nil>})",
+       }, {
+               err:  formatError("use fmt.Formatter"),
+               fmt:  "%#v",
+               want: "use fmt.Formatter",
+       }, {
+               err: fmtTwice("%s %s", "ok", panicValue{}),
+               fmt: "%s",
+               // Different Go versions produce different results.
+               want:   `ok %!s\(PANIC=(String method: )?panic\)/ok %!s\(PANIC=(String method: )?panic\)`,
+               regexp: true,
+       }, {
+               err:  fmtTwice("%o %s", panicValue{}, "ok"),
+               fmt:  "%s",
+               want: "{} ok/{} ok",
+       }, {
+               err: adapted{"adapted", nil},
+               fmt: "%+v",
+               want: "adapted:" +
+                       "\n    detail",
+       }, {
+               err: adapted{"outer", adapted{"mid", adapted{"inner", nil}}},
+               fmt: "%+v",
+               want: "outer:" +
+                       "\n    detail" +
+                       "\n  - mid:" +
+                       "\n    detail" +
+                       "\n  - inner:" +
+                       "\n    detail",
+       }}
+       for i, tc := range testCases {
+               t.Run(fmt.Sprintf("%d/%s", i, tc.fmt), func(t *testing.T) {
+                       got := fmt.Sprintf(tc.fmt, tc.err)
+                       var ok bool
+                       if tc.regexp {
+                               var err error
+                               ok, err = regexp.MatchString(tc.want+"$", got)
+                               if err != nil {
+                                       t.Fatal(err)
+                               }
+                       } else {
+                               ok = got == tc.want
+                       }
+                       if !ok {
+                               t.Errorf("\n got: %q\nwant: %q", got, tc.want)
+                       }
+               })
+       }
+}
+
+func TestAdaptor(t *testing.T) {
+       testCases := []struct {
+               err    error
+               fmt    string
+               want   string
+               regexp bool
+       }{{
+               err: adapted{"adapted", nil},
+               fmt: "%+v",
+               want: "adapted:" +
+                       "\n    detail",
+       }, {
+               err: adapted{"outer", adapted{"mid", adapted{"inner", nil}}},
+               fmt: "%+v",
+               want: "outer:" +
+                       "\n    detail" +
+                       "\n  - mid:" +
+                       "\n    detail" +
+                       "\n  - inner:" +
+                       "\n    detail",
+       }}
+       for i, tc := range testCases {
+               t.Run(fmt.Sprintf("%d/%s", i, tc.fmt), func(t *testing.T) {
+                       got := fmt.Sprintf(tc.fmt, tc.err)
+                       if got != tc.want {
+                               t.Errorf("\n got: %q\nwant: %q", got, tc.want)
+                       }
+               })
+       }
+}
+
+var _ xerrors.Formatter = wrapped{}
+
+type wrapped struct {
+       msg string
+       err error
+}
+
+func (e wrapped) Error() string { return "should call Format" }
+
+func (e wrapped) Format(s fmt.State, verb rune) {
+       xerrors.FormatError(&e, s, verb)
+}
+
+func (e wrapped) FormatError(p xerrors.Printer) (next error) {
+       p.Print(e.msg)
+       p.Detail()
+       p.Print("somefile.go:123")
+       return e.err
+}
+
+var _ xerrors.Formatter = detailed{}
+
+type detailed struct{}
+
+func (e detailed) Error() string { panic("should have called FormatError") }
+
+func (detailed) FormatError(p xerrors.Printer) (next error) {
+       p.Printf("out of %s", "peanuts")
+       p.Detail()
+       p.Print("the elephant is on strike\n")
+       p.Printf("and the %d monkeys\nare laughing", 12)
+       return nil
+}
+
+type withFrameAndMore struct {
+       frame xerrors.Frame
+}
+
+func (e *withFrameAndMore) Error() string { return fmt.Sprint(e) }
+
+func (e *withFrameAndMore) Format(s fmt.State, v rune) {
+       xerrors.FormatError(e, s, v)
+}
+
+func (e *withFrameAndMore) FormatError(p xerrors.Printer) (next error) {
+       p.Print("something")
+       if p.Detail() {
+               e.frame.Format(p)
+               p.Print("something more")
+       }
+       return nil
+}
+
+type spurious string
+
+func (e spurious) Error() string { return fmt.Sprint(e) }
+
+// move to 1_12 test file
+func (e spurious) Format(s fmt.State, verb rune) {
+       xerrors.FormatError(e, s, verb)
+}
+
+func (e spurious) FormatError(p xerrors.Printer) (next error) {
+       p.Print("spurious")
+       p.Detail() // Call detail even if we don't print anything
+       if e == "" {
+               p.Print()
+       } else {
+               p.Print("\n", string(e)) // print extraneous leading newline
+       }
+       return nil
+}
+
+type oneNewline struct {
+       next error
+}
+
+func (e *oneNewline) Error() string { return fmt.Sprint(e) }
+
+func (e *oneNewline) Format(s fmt.State, verb rune) {
+       xerrors.FormatError(e, s, verb)
+}
+
+func (e *oneNewline) FormatError(p xerrors.Printer) (next error) {
+       p.Print("1")
+       p.Print("2")
+       p.Print("3")
+       p.Detail()
+       p.Print("\n")
+       return e.next
+}
+
+type newlineAtEnd struct {
+       next error
+}
+
+func (e *newlineAtEnd) Error() string { return fmt.Sprint(e) }
+
+func (e *newlineAtEnd) Format(s fmt.State, verb rune) {
+       xerrors.FormatError(e, s, verb)
+}
+
+func (e *newlineAtEnd) FormatError(p xerrors.Printer) (next error) {
+       p.Print("newlineAtEnd")
+       p.Detail()
+       p.Print("detail\n")
+       return e.next
+}
+
+type adapted struct {
+       msg string
+       err error
+}
+
+func (e adapted) Error() string { return string(e.msg) }
+
+func (e adapted) Format(s fmt.State, verb rune) {
+       xerrors.FormatError(e, s, verb)
+}
+
+func (e adapted) FormatError(p xerrors.Printer) error {
+       p.Print(e.msg)
+       p.Detail()
+       p.Print("detail")
+       return e.err
+}
+
+// formatError is an error implementing Format instead of xerrors.Formatter.
+// The implementation mimics the implementation of github.com/pkg/errors.
+type formatError string
+
+func (e formatError) Error() string { return string(e) }
+
+func (e formatError) Format(s fmt.State, verb rune) {
+       // Body based on pkg/errors/errors.go
+       switch verb {
+       case 'v':
+               if s.Flag('+') {
+                       io.WriteString(s, string(e))
+                       fmt.Fprintf(s, ":\n%s", "otherfile.go:456")
+                       return
+               }
+               fallthrough
+       case 's':
+               io.WriteString(s, string(e))
+       case 'q':
+               fmt.Fprintf(s, "%q", string(e))
+       }
+}
+
+func (e formatError) GoString() string {
+       panic("should never be called")
+}
+
+type fmtTwiceErr struct {
+       format string
+       args   []interface{}
+}
+
+func fmtTwice(format string, a ...interface{}) error {
+       return fmtTwiceErr{format, a}
+}
+
+func (e fmtTwiceErr) Error() string { return fmt.Sprint(e) }
+
+func (e fmtTwiceErr) Format(s fmt.State, verb rune) {
+       xerrors.FormatError(e, s, verb)
+}
+
+func (e fmtTwiceErr) FormatError(p xerrors.Printer) (next error) {
+       p.Printf(e.format, e.args...)
+       p.Print("/")
+       p.Printf(e.format, e.args...)
+       return nil
+}
+
+func (e fmtTwiceErr) GoString() string {
+       return "2 times " + fmt.Sprintf(e.format, e.args...)
+}
+
+type panicValue struct{}
+
+func (panicValue) String() string { panic("panic") }
+
+var rePath = regexp.MustCompile(`( [^ ]*)xerrors.*test\.`)
+var reLine = regexp.MustCompile(":[0-9]*\n?$")
+
+func cleanPath(s string) string {
+       s = rePath.ReplaceAllString(s, "/path.")
+       s = reLine.ReplaceAllString(s, ":xxx")
+       s = strings.Replace(s, "\n   ", "", -1)
+       s = strings.Replace(s, " /", "/", -1)
+       return s
+}
+
+func errToParts(err error) (a []string) {
+       for err != nil {
+               var p testPrinter
+               if xerrors.Unwrap(err) != nil {
+                       p.str += "wraps:"
+               }
+               f, ok := err.(xerrors.Formatter)
+               if !ok {
+                       a = append(a, err.Error())
+                       break
+               }
+               err = f.FormatError(&p)
+               a = append(a, cleanPath(p.str))
+       }
+       return a
+
+}
+
+type testPrinter struct {
+       str string
+}
+
+func (p *testPrinter) Print(a ...interface{}) {
+       p.str += fmt.Sprint(a...)
+}
+
+func (p *testPrinter) Printf(format string, a ...interface{}) {
+       p.str += fmt.Sprintf(format, a...)
+}
+
+func (p *testPrinter) Detail() bool {
+       p.str += " /"
+       return true
+}