diff options
Diffstat (limited to 'vendor/github.com/getlantern/errors')
-rw-r--r-- | vendor/github.com/getlantern/errors/errors.go | 566 | ||||
-rw-r--r-- | vendor/github.com/getlantern/errors/errors_test.go | 142 | ||||
-rw-r--r-- | vendor/github.com/getlantern/errors/hide.go | 50 |
3 files changed, 0 insertions, 758 deletions
diff --git a/vendor/github.com/getlantern/errors/errors.go b/vendor/github.com/getlantern/errors/errors.go deleted file mode 100644 index 8b2b84f..0000000 --- a/vendor/github.com/getlantern/errors/errors.go +++ /dev/null @@ -1,566 +0,0 @@ -/* -Package errors defines error types used across Lantern project. - - n, err := Foo() - if err != nil { - return n, errors.New("Unable to do Foo: %v", err) - } - -or - - n, err := Foo() - return n, errors.Wrap(err) - -New() method will create a new error with err as its cause. Wrap will wrap err, -returning nil if err is nil. If err is an error from Go's standard library, -errors will extract details from that error, at least the Go type name and the -return value of err.Error(). - -One can record the operation on which the error occurred using Op(): - - return n, errors.New("Unable to do Foo: %v", err).Op("FooDooer") - -One can also record additional data: - - return n, errors. - New("Unable to do Foo: %v", err). - Op("FooDooer"). - With("mydata", "myvalue"). - With("moredata", 5) - -When used with github.com/getlantern/ops, Error captures its current context -and propagates that data for use in calling layers. - -When used with github.com/getlantern/golog, Error provides stacktraces: - - Hello World - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) - Caused by: World - at github.com/getlantern/errors.buildCause (errors_test.go:999) - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) - Caused by: orld - Caused by: ld - at github.com/getlantern/errors.buildSubSubCause (errors_test.go:999) - at github.com/getlantern/errors.buildSubCause (errors_test.go:999) - at github.com/getlantern/errors.buildCause (errors_test.go:999) - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) - Caused by: d - -It's the caller's responsibility to avoid race conditions accessing the same -error instance from multiple goroutines. -*/ -package errors - -import ( - "bufio" - "bytes" - "crypto/tls" - "crypto/x509" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "net" - "net/http" - "net/textproto" - "net/url" - "os" - "os/exec" - "reflect" - "runtime" - "strconv" - "strings" - "syscall" - "time" - "unicode" - - "github.com/getlantern/context" - "github.com/getlantern/hidden" - "github.com/getlantern/ops" - "github.com/go-stack/stack" -) - -// Error wraps system and application defined errors in unified structure for -// reporting and logging. It's not meant to be created directly. User New(), -// Wrap() and Report() instead. -type Error interface { - error - context.Contextual - - // ErrorClean returns a non-parameterized version of the error whenever - // possible. For example, if the error text is: - // - // unable to dial www.google.com caused by: i/o timeout - // - // ErrorClean might return: - // - // unable to dial %v caused by: %v - // - // This can be useful when performing analytics on the error. - ErrorClean() string - - // MultiLinePrinter implements the interface golog.MultiLine - MultiLinePrinter() func(buf *bytes.Buffer) bool - - // Op attaches a hint of the operation triggers this Error. Many error types - // returned by net and os package have Op pre-filled. - Op(op string) Error - - // With attaches arbitrary field to the error. keys will be normalized as - // underscore_divided_words, so all characters except letters and numbers will - // be replaced with underscores, and all letters will be lowercased. - With(key string, value interface{}) Error - - // RootCause returns the bottom-most cause of this Error. If the Error - // resulted from wrapping a plain error, the wrapped error will be returned as - // the cause. - RootCause() error -} - -type structured struct { - id uint64 - hiddenID string - data context.Map - context context.Map - wrapped error - cause Error - callStack stack.CallStack -} - -// New creates an Error with supplied description and format arguments to the -// description. If any of the arguments is an error, we use that as the cause. -func New(desc string, args ...interface{}) Error { - return NewOffset(1, desc, args...) -} - -// NewOffset is like New but offsets the stack by the given offset. This is -// useful for utilities like golog that may create errors on behalf of others. -func NewOffset(offset int, desc string, args ...interface{}) Error { - var cause error - for _, arg := range args { - err, isError := arg.(error) - if isError { - cause = err - break - } - } - e := buildError(desc, fmt.Sprintf(desc, args...), nil, Wrap(cause)) - e.attachStack(2 + offset) - return e -} - -// Wrap creates an Error based on the information in an error instance. It -// returns nil if the error passed in is nil, so we can simply call -// errors.Wrap(s.l.Close()) regardless there's an error or not. If the error is -// already wrapped, it is returned as is. -func Wrap(err error) Error { - return wrapSkipFrames(err, 1) -} - -// Fill implements the method from the context.Contextual interface. -func (e *structured) Fill(m context.Map) { - if e != nil { - if e.cause != nil { - // Include data from cause, which supercedes context - e.cause.Fill(m) - } - // Include the context, which supercedes the cause - for key, value := range e.context { - m[key] = value - } - // Now include the error's data, which supercedes everything - for key, value := range e.data { - m[key] = value - } - } -} - -func (e *structured) Op(op string) Error { - e.data["error_op"] = op - return e -} - -func (e *structured) With(key string, value interface{}) Error { - parts := strings.FieldsFunc(key, func(c rune) bool { - return !unicode.IsLetter(c) && !unicode.IsNumber(c) - }) - k := strings.ToLower(strings.Join(parts, "_")) - if k == "error" || k == "error_op" { - // Never overwrite these - return e - } - switch actual := value.(type) { - case string, int, bool, time.Time: - e.data[k] = actual - default: - e.data[k] = fmt.Sprint(actual) - } - return e -} - -func (e *structured) RootCause() error { - if e.cause == nil { - if e.wrapped != nil { - return e.wrapped - } - return e - } - return e.cause.RootCause() -} - -func (e *structured) ErrorClean() string { - return e.data["error"].(string) -} - -// Error satisfies the error interface -func (e *structured) Error() string { - return e.data["error_text"].(string) + e.hiddenID -} - -func (e *structured) MultiLinePrinter() func(buf *bytes.Buffer) bool { - first := true - indent := false - err := e - stackPosition := 0 - switchedCause := false - return func(buf *bytes.Buffer) bool { - if indent { - buf.WriteString(" ") - } - if first { - buf.WriteString(e.Error()) - first = false - indent = true - return true - } - if switchedCause { - fmt.Fprintf(buf, "Caused by: %v", err) - if err.callStack != nil && len(err.callStack) > 0 { - switchedCause = false - indent = true - return true - } - if err.cause == nil { - return false - } - err = err.cause.(*structured) - return true - } - if stackPosition < len(err.callStack) { - buf.WriteString("at ") - call := err.callStack[stackPosition] - fmt.Fprintf(buf, "%+n (%s:%d)", call, call, call) - stackPosition++ - } - if stackPosition >= len(err.callStack) { - switch cause := err.cause.(type) { - case *structured: - err = cause - indent = false - stackPosition = 0 - switchedCause = true - default: - return false - } - } - return err != nil - } -} - -func wrapSkipFrames(err error, skip int) Error { - if err == nil { - return nil - } - - // Look for *structureds - if e, ok := err.(*structured); ok { - return e - } - - var cause Error - // Look for hidden *structureds - hiddenIDs, err2 := hidden.Extract(err.Error()) - if err2 == nil && len(hiddenIDs) > 0 { - // Take the first hidden ID as our cause - cause = get(hiddenIDs[0]) - } - - // Create a new *structured - return buildError("", "", err, cause) -} - -func (e *structured) attachStack(skip int) { - call := stack.Caller(skip) - e.callStack = stack.Trace().TrimBelow(call) - e.data["error_location"] = fmt.Sprintf("%+n (%s:%d)", call, call, call) -} - -func buildError(desc string, fullText string, wrapped error, cause Error) *structured { - e := &structured{ - data: make(context.Map), - // We capture the current context to allow it to propagate to higher layers. - context: ops.AsMap(nil, false), - wrapped: wrapped, - cause: cause, - } - e.save() - - errorType := "errors.Error" - if wrapped != nil { - op, goType, wrappedDesc, extra := parseError(wrapped) - if desc == "" { - desc = wrappedDesc - } - e.Op(op) - errorType = goType - if extra != nil { - for key, value := range extra { - e.data[key] = value - } - } - } - - cleanedDesc := hidden.Clean(desc) - e.data["error"] = cleanedDesc - if fullText != "" { - e.data["error_text"] = hidden.Clean(fullText) - } else { - e.data["error_text"] = cleanedDesc - } - e.data["error_type"] = errorType - - return e -} - -func parseError(err error) (op string, goType string, desc string, extra map[string]string) { - extra = make(map[string]string) - - // interfaces - if _, ok := err.(net.Error); ok { - if opError, ok := err.(*net.OpError); ok { - op = opError.Op - if opError.Source != nil { - extra["remote_addr"] = opError.Source.String() - } - if opError.Addr != nil { - extra["local_addr"] = opError.Addr.String() - } - extra["network"] = opError.Net - err = opError.Err - } - switch actual := err.(type) { - case *net.AddrError: - goType = "net.AddrError" - desc = actual.Err - extra["addr"] = actual.Addr - case *net.DNSError: - goType = "net.DNSError" - desc = actual.Err - extra["domain"] = actual.Name - if actual.Server != "" { - extra["dns_server"] = actual.Server - } - case *net.InvalidAddrError: - goType = "net.InvalidAddrError" - desc = actual.Error() - case *net.ParseError: - goType = "net.ParseError" - desc = "invalid " + actual.Type - extra["text_to_parse"] = actual.Text - case net.UnknownNetworkError: - goType = "net.UnknownNetworkError" - desc = "unknown network" - case syscall.Errno: - goType = "syscall.Errno" - desc = actual.Error() - case *url.Error: - goType = "url.Error" - desc = actual.Err.Error() - op = actual.Op - default: - goType = reflect.TypeOf(err).String() - desc = err.Error() - } - return - } - if _, ok := err.(runtime.Error); ok { - desc = err.Error() - switch err.(type) { - case *runtime.TypeAssertionError: - goType = "runtime.TypeAssertionError" - default: - goType = reflect.TypeOf(err).String() - } - return - } - - // structs - switch actual := err.(type) { - case *http.ProtocolError: - desc = actual.ErrorString - if name, ok := httpProtocolErrors[err]; ok { - goType = name - } else { - goType = "http.ProtocolError" - } - case url.EscapeError, *url.EscapeError: - goType = "url.EscapeError" - desc = "invalid URL escape" - case url.InvalidHostError, *url.InvalidHostError: - goType = "url.InvalidHostError" - desc = "invalid character in host name" - case *textproto.Error: - goType = "textproto.Error" - desc = actual.Error() - case textproto.ProtocolError, *textproto.ProtocolError: - goType = "textproto.ProtocolError" - desc = actual.Error() - - case tls.RecordHeaderError: - goType = "tls.RecordHeaderError" - desc = actual.Msg - extra["header"] = hex.EncodeToString(actual.RecordHeader[:]) - case x509.CertificateInvalidError: - goType = "x509.CertificateInvalidError" - desc = actual.Error() - case x509.ConstraintViolationError: - goType = "x509.ConstraintViolationError" - desc = actual.Error() - case x509.HostnameError: - goType = "x509.HostnameError" - desc = actual.Error() - extra["host"] = actual.Host - case x509.InsecureAlgorithmError: - goType = "x509.InsecureAlgorithmError" - desc = actual.Error() - case x509.SystemRootsError: - goType = "x509.SystemRootsError" - desc = actual.Error() - case x509.UnhandledCriticalExtension: - goType = "x509.UnhandledCriticalExtension" - desc = actual.Error() - case x509.UnknownAuthorityError: - goType = "x509.UnknownAuthorityError" - desc = actual.Error() - case hex.InvalidByteError: - goType = "hex.InvalidByteError" - desc = "invalid byte" - case *json.InvalidUTF8Error: - goType = "json.InvalidUTF8Error" - desc = "invalid UTF-8 in string" - case *json.InvalidUnmarshalError: - goType = "json.InvalidUnmarshalError" - desc = actual.Error() - case *json.MarshalerError: - goType = "json.MarshalerError" - desc = actual.Error() - case *json.SyntaxError: - goType = "json.SyntaxError" - desc = actual.Error() - case *json.UnmarshalFieldError: - goType = "json.UnmarshalFieldError" - desc = actual.Error() - case *json.UnmarshalTypeError: - goType = "json.UnmarshalTypeError" - desc = actual.Error() - case *json.UnsupportedTypeError: - goType = "json.UnsupportedTypeError" - desc = actual.Error() - case *json.UnsupportedValueError: - goType = "json.UnsupportedValueError" - desc = actual.Error() - - case *os.LinkError: - goType = "os.LinkError" - desc = actual.Error() - case *os.PathError: - goType = "os.PathError" - op = actual.Op - desc = actual.Err.Error() - case *os.SyscallError: - goType = "os.SyscallError" - op = actual.Syscall - desc = actual.Err.Error() - case *exec.Error: - goType = "exec.Error" - desc = actual.Err.Error() - case *exec.ExitError: - goType = "exec.ExitError" - desc = actual.Error() - // TODO: limit the length - extra["stderr"] = string(actual.Stderr) - case *strconv.NumError: - goType = "strconv.NumError" - desc = actual.Err.Error() - extra["function"] = actual.Func - case *time.ParseError: - goType = "time.ParseError" - desc = actual.Message - default: - desc = err.Error() - if t, ok := miscErrors[err]; ok { - goType = t - return - } - goType = reflect.TypeOf(err).String() - } - return -} - -var httpProtocolErrors = map[error]string{ - http.ErrHeaderTooLong: "http.ErrHeaderTooLong", - http.ErrShortBody: "http.ErrShortBody", - http.ErrNotSupported: "http.ErrNotSupported", - http.ErrUnexpectedTrailer: "http.ErrUnexpectedTrailer", - http.ErrMissingContentLength: "http.ErrMissingContentLength", - http.ErrNotMultipart: "http.ErrNotMultipart", - http.ErrMissingBoundary: "http.ErrMissingBoundary", -} - -var miscErrors = map[error]string{ - bufio.ErrInvalidUnreadByte: "bufio.ErrInvalidUnreadByte", - bufio.ErrInvalidUnreadRune: "bufio.ErrInvalidUnreadRune", - bufio.ErrBufferFull: "bufio.ErrBufferFull", - bufio.ErrNegativeCount: "bufio.ErrNegativeCount", - bufio.ErrTooLong: "bufio.ErrTooLong", - bufio.ErrNegativeAdvance: "bufio.ErrNegativeAdvance", - bufio.ErrAdvanceTooFar: "bufio.ErrAdvanceTooFar", - bufio.ErrFinalToken: "bufio.ErrFinalToken", - - http.ErrWriteAfterFlush: "http.ErrWriteAfterFlush", - http.ErrBodyNotAllowed: "http.ErrBodyNotAllowed", - http.ErrHijacked: "http.ErrHijacked", - http.ErrContentLength: "http.ErrContentLength", - http.ErrBodyReadAfterClose: "http.ErrBodyReadAfterClose", - http.ErrHandlerTimeout: "http.ErrHandlerTimeout", - http.ErrLineTooLong: "http.ErrLineTooLong", - http.ErrMissingFile: "http.ErrMissingFile", - http.ErrNoCookie: "http.ErrNoCookie", - http.ErrNoLocation: "http.ErrNoLocation", - http.ErrSkipAltProtocol: "http.ErrSkipAltProtocol", - - io.EOF: "io.EOF", - io.ErrClosedPipe: "io.ErrClosedPipe", - io.ErrNoProgress: "io.ErrNoProgress", - io.ErrShortBuffer: "io.ErrShortBuffer", - io.ErrShortWrite: "io.ErrShortWrite", - io.ErrUnexpectedEOF: "io.ErrUnexpectedEOF", - - os.ErrInvalid: "os.ErrInvalid", - os.ErrPermission: "os.ErrPermission", - os.ErrExist: "os.ErrExist", - os.ErrNotExist: "os.ErrNotExist", - - exec.ErrNotFound: "exec.ErrNotFound", - - x509.ErrUnsupportedAlgorithm: "x509.ErrUnsupportedAlgorithm", - x509.IncorrectPasswordError: "x509.IncorrectPasswordError", - - hex.ErrLength: "hex.ErrLength", -} diff --git a/vendor/github.com/getlantern/errors/errors_test.go b/vendor/github.com/getlantern/errors/errors_test.go deleted file mode 100644 index 7c4887a..0000000 --- a/vendor/github.com/getlantern/errors/errors_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package errors - -import ( - "bytes" - "fmt" - "regexp" - "testing" - - "github.com/getlantern/context" - "github.com/getlantern/hidden" - "github.com/getlantern/ops" - "github.com/stretchr/testify/assert" -) - -var ( - replaceNumbers = regexp.MustCompile("[0-9]+") -) - -func TestFull(t *testing.T) { - var firstErr Error - - // Iterate past the size of the hidden buffer - for i := 0; i < len(hiddenErrors)*2; i++ { - op := ops.Begin("op1").Set("ca", 100).Set("cd", 100) - e := New("Hello %v", "There").Op("My Op").With("DaTa_1", 1) - op.End() - if firstErr == nil { - firstErr = e - } - assert.Equal(t, "Hello There", e.Error()[:11]) - op = ops.Begin("op2").Set("ca", 200).Set("cb", 200).Set("cc", 200) - e3 := Wrap(fmt.Errorf("I'm wrapping your text: %v", e)).Op("outer op").With("dATA+1", i).With("cb", 300) - op.End() - assert.Equal(t, e, e3.(*structured).cause, "Wrapping a regular error should have extracted the contained *Error") - m := make(context.Map) - e3.Fill(m) - assert.Equal(t, i, m["data_1"], "Error's data should dominate all") - assert.Equal(t, 200, m["ca"], "Error's context should dominate cause") - assert.Equal(t, 300, m["cb"], "Error's data should dominate its context") - assert.Equal(t, 200, m["cc"], "Error's context should come through") - assert.Equal(t, 100, m["cd"], "Cause's context should come through") - assert.Equal(t, "My Op", e.(*structured).data["error_op"], "Op should be available from cause") - - for _, call := range e3.(*structured).callStack { - t.Logf("at %v", call) - } - } - - e3 := Wrap(fmt.Errorf("I'm wrapping your text: %v", firstErr)).With("a", 2) - assert.Nil(t, e3.(*structured).cause, "Wrapping an *Error that's no longer buffered should have yielded no cause") -} - -func TestNewWithCause(t *testing.T) { - cause := buildCause() - outer := New("Hello %v", cause) - assert.Equal(t, "Hello World", hidden.Clean(outer.Error())) - assert.Equal(t, "Hello %v", outer.(*structured).ErrorClean()) - assert.Equal(t, - "github.com/getlantern/errors.TestNewWithCause (errors_test.go:999)", - replaceNumbers.ReplaceAllString(outer.(*structured).data["error_location"].(string), "999")) - assert.Equal(t, cause, outer.(*structured).cause) - - // Make sure that stacktrace prints out okay - buf := &bytes.Buffer{} - print := outer.MultiLinePrinter() - for { - more := print(buf) - buf.WriteByte('\n') - if !more { - break - } - } - expected := `Hello World - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) -Caused by: World - at github.com/getlantern/errors.buildCause (errors_test.go:999) - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) -Caused by: orld -Caused by: ld - at github.com/getlantern/errors.buildSubSubCause (errors_test.go:999) - at github.com/getlantern/errors.buildSubCause (errors_test.go:999) - at github.com/getlantern/errors.buildCause (errors_test.go:999) - at github.com/getlantern/errors.TestNewWithCause (errors_test.go:999) - at testing.tRunner (testing.go:999) - at runtime.goexit (asm_amd999.s:999) -Caused by: d -` - - assert.Equal(t, expected, replaceNumbers.ReplaceAllString(hidden.Clean(buf.String()), "999")) - assert.Equal(t, buildSubSubSubCause(), outer.RootCause()) -} - -func buildCause() Error { - return New("W%v", buildSubCause()) -} - -func buildSubCause() error { - return fmt.Errorf("or%v", buildSubSubCause()) -} - -func buildSubSubCause() error { - return New("l%v", buildSubSubSubCause()) -} - -func buildSubSubSubCause() error { - return fmt.Errorf("d") -} - -func TestWrapNil(t *testing.T) { - assert.Nil(t, doWrapNil()) -} - -func doWrapNil() error { - return Wrap(nil) -} - -func TestHiddenWithCause(t *testing.T) { - e1 := fmt.Errorf("I failed %v", "dude") - e2 := New("I wrap: %v", e1) - e3 := fmt.Errorf("Hiding %v", e2) - // clear hidden buffer - hiddenErrors = make([]*structured, 100) - e4 := Wrap(e3) - e5 := New("I'm really outer: %v", e4) - - buf := &bytes.Buffer{} - print := e5.MultiLinePrinter() - for { - more := print(buf) - buf.WriteByte('\n') - if !more { - break - } - } - fmt.Println(buf.String()) - // We're not asserting the output because we're just making sure that printing - // doesn't panic. If we get to this point without panicking, we're happy. -} diff --git a/vendor/github.com/getlantern/errors/hide.go b/vendor/github.com/getlantern/errors/hide.go deleted file mode 100644 index f10d863..0000000 --- a/vendor/github.com/getlantern/errors/hide.go +++ /dev/null @@ -1,50 +0,0 @@ -package errors - -import ( - "encoding/binary" - "sync" - - "github.com/getlantern/hidden" -) - -var ( - hiddenErrors = make([]*structured, 100) - nextID = uint64(0) - hiddenMutex sync.RWMutex -) - -// This trick saves the error to a ring buffer and embeds a non-printing -// hiddenID in the error's description, so that if the errors is later wrapped -// by a standard error using something like -// fmt.Errorf("An error occurred: %v", thisError), we can subsequently extract -// the error simply using the hiddenID in the string. -func (e *structured) save() { - hiddenMutex.Lock() - b := make([]byte, 8) - binary.BigEndian.PutUint64(b, nextID) - e.id = nextID - e.hiddenID = hidden.ToString(b) - hiddenErrors[idxForID(nextID)] = e - nextID++ - hiddenMutex.Unlock() -} - -func get(hiddenID []byte) Error { - if len(hiddenID) != 8 { - return nil - } - id := binary.BigEndian.Uint64(hiddenID) - hiddenMutex.RLock() - err := hiddenErrors[idxForID(id)] - hiddenMutex.RUnlock() - if err != nil && err.id == id { - // Found it! - return err - } - // buffer has rolled over - return nil -} - -func idxForID(id uint64) int { - return int(id % uint64(len(hiddenErrors))) -} |