Remove error package and cause functions (#5784)
parent
217fb470a7
commit
cef992a395
@ -1,154 +0,0 @@ |
|||||||
/* |
|
||||||
* Minio Cloud Storage, (C) 2017 Minio, Inc. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package errors |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
"os" |
|
||||||
"path/filepath" |
|
||||||
"runtime" |
|
||||||
"strings" |
|
||||||
) |
|
||||||
|
|
||||||
var ( |
|
||||||
// Package path of the project.
|
|
||||||
pkgPath string |
|
||||||
) |
|
||||||
|
|
||||||
// Init - initialize package path.
|
|
||||||
func Init(gopath string, p string) { |
|
||||||
pkgPath = filepath.Join(gopath, "src", p) + string(os.PathSeparator) |
|
||||||
} |
|
||||||
|
|
||||||
// stackInfo - Represents a stack frame in the stack trace.
|
|
||||||
type stackInfo struct { |
|
||||||
Filename string `json:"fileName"` // File where error occurred
|
|
||||||
Line int `json:"line"` // Line where error occurred
|
|
||||||
Name string `json:"name"` // Name of the function where error occurred
|
|
||||||
} |
|
||||||
|
|
||||||
// Error - error type containing cause and the stack trace.
|
|
||||||
type Error struct { |
|
||||||
Cause error // Holds the cause error
|
|
||||||
stack []stackInfo // Stack trace info.
|
|
||||||
errs []error // Useful for XL to hold errors from all disks
|
|
||||||
} |
|
||||||
|
|
||||||
// Implement error interface.
|
|
||||||
func (e Error) Error() string { |
|
||||||
return e.Cause.Error() |
|
||||||
} |
|
||||||
|
|
||||||
// Stack - returns slice of stack trace.
|
|
||||||
func (e Error) Stack() []string { |
|
||||||
var stack []string |
|
||||||
for _, info := range e.stack { |
|
||||||
stack = append(stack, fmt.Sprintf("%s:%d:%s()", info.Filename, info.Line, info.Name)) |
|
||||||
} |
|
||||||
return stack |
|
||||||
} |
|
||||||
|
|
||||||
// Trace - return new Error type.
|
|
||||||
func Trace(e error, errs ...error) error { |
|
||||||
// Error is nil nothing to do return nil.
|
|
||||||
if e == nil { |
|
||||||
return nil |
|
||||||
} |
|
||||||
|
|
||||||
// Already a trace error should be returned as is.
|
|
||||||
if _, ok := e.(*Error); ok { |
|
||||||
return e |
|
||||||
} |
|
||||||
|
|
||||||
err := &Error{} |
|
||||||
err.Cause = e |
|
||||||
err.errs = errs |
|
||||||
|
|
||||||
stack := make([]uintptr, 40) |
|
||||||
length := runtime.Callers(2, stack) |
|
||||||
if length > len(stack) { |
|
||||||
length = len(stack) |
|
||||||
} |
|
||||||
stack = stack[:length] |
|
||||||
|
|
||||||
for _, pc := range stack { |
|
||||||
pc = pc - 1 |
|
||||||
fn := runtime.FuncForPC(pc) |
|
||||||
file, line := fn.FileLine(pc) |
|
||||||
|
|
||||||
var suffixFound bool |
|
||||||
for _, ignoreName := range []string{ |
|
||||||
"runtime.", |
|
||||||
"testing.", |
|
||||||
} { |
|
||||||
if strings.HasPrefix(fn.Name(), ignoreName) { |
|
||||||
suffixFound = true |
|
||||||
break |
|
||||||
} |
|
||||||
} |
|
||||||
if suffixFound { |
|
||||||
continue |
|
||||||
} |
|
||||||
_, name := filepath.Split(fn.Name()) |
|
||||||
name = strings.SplitN(name, ".", 2)[1] |
|
||||||
file = filepath.FromSlash(strings.TrimPrefix(filepath.ToSlash(file), filepath.ToSlash(pkgPath))) |
|
||||||
err.stack = append(err.stack, stackInfo{ |
|
||||||
Filename: file, |
|
||||||
Line: line, |
|
||||||
Name: name, |
|
||||||
}) |
|
||||||
} |
|
||||||
|
|
||||||
return err |
|
||||||
} |
|
||||||
|
|
||||||
// Cause - Returns the underlying cause error.
|
|
||||||
func Cause(err error) error { |
|
||||||
if e, ok := err.(*Error); ok { |
|
||||||
err = e.Cause |
|
||||||
} |
|
||||||
return err |
|
||||||
} |
|
||||||
|
|
||||||
// Causes - Returns slice of underlying cause error.
|
|
||||||
func Causes(errs []error) (cerrs []error) { |
|
||||||
for _, err := range errs { |
|
||||||
cerrs = append(cerrs, Cause(err)) |
|
||||||
} |
|
||||||
return cerrs |
|
||||||
} |
|
||||||
|
|
||||||
// IsErrIgnored returns whether given error is ignored or not.
|
|
||||||
func IsErrIgnored(err error, ignoredErrs ...error) bool { |
|
||||||
return IsErr(err, ignoredErrs...) |
|
||||||
} |
|
||||||
|
|
||||||
// IsErr returns whether given error is exact error.
|
|
||||||
func IsErr(err error, errs ...error) bool { |
|
||||||
err = Cause(err) |
|
||||||
for _, exactErr := range errs { |
|
||||||
if err == exactErr { |
|
||||||
return true |
|
||||||
} |
|
||||||
} |
|
||||||
return false |
|
||||||
} |
|
||||||
|
|
||||||
// Tracef behaves like fmt.Errorf but adds traces to the returned error.
|
|
||||||
func Tracef(format string, args ...interface{}) error { |
|
||||||
return Trace(fmt.Errorf(format, args...)) |
|
||||||
} |
|
@ -1,120 +0,0 @@ |
|||||||
/* |
|
||||||
* Minio Cloud Storage, (C) 2017 Minio, Inc. |
|
||||||
* |
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
||||||
* you may not use this file except in compliance with the License. |
|
||||||
* You may obtain a copy of the License at |
|
||||||
* |
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
* |
|
||||||
* Unless required by applicable law or agreed to in writing, software |
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, |
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
||||||
* See the License for the specific language governing permissions and |
|
||||||
* limitations under the License. |
|
||||||
*/ |
|
||||||
|
|
||||||
package errors |
|
||||||
|
|
||||||
import ( |
|
||||||
"fmt" |
|
||||||
"go/build" |
|
||||||
"path/filepath" |
|
||||||
"reflect" |
|
||||||
"strings" |
|
||||||
"testing" |
|
||||||
) |
|
||||||
|
|
||||||
// Test trace errors.
|
|
||||||
func TestTrace(t *testing.T) { |
|
||||||
var errExpectedCause = fmt.Errorf("traceable error") |
|
||||||
var testCases = []struct { |
|
||||||
expectedCauseErr error |
|
||||||
}{ |
|
||||||
{ |
|
||||||
expectedCauseErr: nil, |
|
||||||
}, |
|
||||||
{ |
|
||||||
expectedCauseErr: errExpectedCause, |
|
||||||
}, |
|
||||||
{ |
|
||||||
expectedCauseErr: Trace(errExpectedCause), |
|
||||||
}, |
|
||||||
} |
|
||||||
for i, testCase := range testCases { |
|
||||||
if err := Trace(testCase.expectedCauseErr); err != nil { |
|
||||||
if errGotCause := Cause(err); errGotCause != Cause(testCase.expectedCauseErr) { |
|
||||||
t.Errorf("Test: %d Expected %s, got %s", i+1, testCase.expectedCauseErr, errGotCause) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Test if isErrIgnored works correctly.
|
|
||||||
func TestIsErrIgnored(t *testing.T) { |
|
||||||
var errIgnored = fmt.Errorf("ignored error") |
|
||||||
var testCases = []struct { |
|
||||||
err error |
|
||||||
ignored bool |
|
||||||
}{ |
|
||||||
{ |
|
||||||
err: nil, |
|
||||||
ignored: false, |
|
||||||
}, |
|
||||||
{ |
|
||||||
err: errIgnored, |
|
||||||
ignored: true, |
|
||||||
}, |
|
||||||
{ |
|
||||||
err: Trace(errIgnored), |
|
||||||
ignored: true, |
|
||||||
}, |
|
||||||
} |
|
||||||
for i, testCase := range testCases { |
|
||||||
if ok := IsErrIgnored(testCase.err, errIgnored); ok != testCase.ignored { |
|
||||||
t.Errorf("Test: %d, Expected %t, got %t", i+1, testCase.ignored, ok) |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Tests if pkgPath is set properly in init.
|
|
||||||
func TestInit(t *testing.T) { |
|
||||||
Init("/home/test/go", "test") |
|
||||||
if filepath.ToSlash(pkgPath) != "/home/test/go/src/test/" { |
|
||||||
t.Fatalf("Expected pkgPath to be \"/home/test/go/src/test/\", found %s", pkgPath) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Tests stack output.
|
|
||||||
func TestStack(t *testing.T) { |
|
||||||
Init(build.Default.GOPATH, "github.com/minio/minio") |
|
||||||
|
|
||||||
err := Trace(fmt.Errorf("traceable error")) |
|
||||||
if terr, ok := err.(*Error); ok { |
|
||||||
if !strings.HasSuffix(terr.Stack()[0], "TestStack()") { |
|
||||||
t.Errorf("Expected suffix \"TestStack()\", got %s", terr.Stack()[0]) |
|
||||||
} |
|
||||||
} |
|
||||||
// Test if the cause error is returned properly with the underlying string.
|
|
||||||
if err.Error() != "traceable error" { |
|
||||||
t.Errorf("Expected \"traceable error\", got %s", err.Error()) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Tests converting error causes.
|
|
||||||
func TestErrCauses(t *testing.T) { |
|
||||||
errTraceableError := fmt.Errorf("traceable error") |
|
||||||
var errs = []error{ |
|
||||||
errTraceableError, |
|
||||||
errTraceableError, |
|
||||||
errTraceableError, |
|
||||||
} |
|
||||||
var terrs []error |
|
||||||
for _, err := range errs { |
|
||||||
terrs = append(terrs, Trace(err)) |
|
||||||
} |
|
||||||
cerrs := Causes(terrs) |
|
||||||
if !reflect.DeepEqual(errs, cerrs) { |
|
||||||
t.Errorf("Expected %#v, got %#v", errs, cerrs) |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue