Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return bool from XXXOf functions #18

Merged
merged 2 commits into from Jan 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 21 additions & 6 deletions README.md
Expand Up @@ -101,17 +101,32 @@ func Handler(w http.ResponseWriter, r *http.Request) {
}
}

func HandleError(w http.ResponseWriter, err error) {
switch failure.CodeOf(err) {
func getHTTPStatus(err error) int {
c, ok := failure.CodeOf(err)
if !ok {
return http.StatusInternalServerError
}
switch c {
case NotFound:
w.WriteHeader(http.StatusNotFound)
return http.StatusNotFound
case Forbidden:
w.WriteHeader(http.StatusForbidden)
return http.StatusForbidden
default:
w.WriteHeader(http.StatusInternalServerError)
return http.StatusInternalServerError
}
}

io.WriteString(w, failure.MessageOf(err))
func getMessage(err error) string {
msg, ok := failure.MessageOf(err)
if ok {
return msg
}
return "Error"
}

func HandleError(w http.ResponseWriter, err error) {
w.WriteHeader(getHTTPStatus(err))
io.WriteString(w, getMessage(err))

fmt.Println(err)
// main.GetProject: code(forbidden): main.GetACL: code(not_found)
Expand Down
10 changes: 6 additions & 4 deletions callstack_test.go
Expand Up @@ -36,7 +36,9 @@ func Y() error {
func TestCallStackFromPkgErrors(t *testing.T) {
err := Y()

fs := failure.CallStackOf(err).Frames()
cs, ok := failure.CallStackOf(err)
assert.True(t, ok)
fs := cs.Frames()

assert.Contains(t, fs[0].Path(), "github.com/morikuni/failure/callstack_test.go")
assert.Contains(t, fs[0].File(), "callstack_test.go")
Expand All @@ -63,12 +65,12 @@ func TestCallStack_Format(t *testing.T) {
fmt.Sprintf("%s", cs),
)
assert.Regexp(t,
`\[\]failure.Frame{/.+/github.com/morikuni/failure/callstack_test.go:13, /.+/github.com/morikuni/failure/callstack_test.go:55, .*}`,
`\[\]failure.Frame{/.+/github.com/morikuni/failure/callstack_test.go:13, /.+/github.com/morikuni/failure/callstack_test.go:57, .*}`,
fmt.Sprintf("%#v", cs),
)
assert.Regexp(t,
`\[failure_test.X\] /.+/github.com/morikuni/failure/callstack_test.go:13
\[failure_test.TestCallStack_Format\] /.+/github.com/morikuni/failure/callstack_test.go:55
\[failure_test.TestCallStack_Format\] /.+/github.com/morikuni/failure/callstack_test.go:57
\[.*`,
fmt.Sprintf("%+v", cs),
)
Expand Down Expand Up @@ -104,7 +106,7 @@ func TestCallStack_Frames(t *testing.T) {
assert.Equal(t, 13, fs[0].Line())
assert.Equal(t, "X", fs[0].Func())

assert.Equal(t, 99, fs[1].Line())
assert.Equal(t, 101, fs[1].Line())
assert.Equal(t, "TestCallStack_Frames", fs[1].Func())
}

Expand Down
7 changes: 4 additions & 3 deletions code.go
Expand Up @@ -8,9 +8,10 @@ func Is(err error, codes ...Code) bool {
return false
}

c := CodeOf(err)
if c == nil {
return false
c, ok := CodeOf(err)
if !ok {
// continue process (don't return) to accept the case Is(err, nil).
c = nil
}

for i := range codes {
Expand Down
4 changes: 4 additions & 0 deletions code_test.go
@@ -1,6 +1,7 @@
package failure_test

import (
"errors"
"testing"

"io"
Expand Down Expand Up @@ -64,4 +65,7 @@ func TestIs(t *testing.T) {
assert.False(t, failure.Is(nil, A, B))
assert.False(t, failure.Is(io.EOF, A, B))
assert.False(t, failure.Is(errA))

assert.True(t, failure.Is(nil, nil))
assert.True(t, failure.Is(errors.New("error"), nil))
}
8 changes: 4 additions & 4 deletions failure.go
Expand Up @@ -34,9 +34,9 @@ func (f Failure) Error() string {
}

// CodeOf extracts an error Code from the error.
func CodeOf(err error) Code {
func CodeOf(err error) (Code, bool) {
if err == nil {
return nil
return nil, false
}

type codeGetter interface {
Expand All @@ -47,11 +47,11 @@ func CodeOf(err error) Code {
for i.Next() {
err := i.Error()
if g, ok := err.(codeGetter); ok {
return g.GetCode()
return g.GetCode(), true
}
}

return nil
return nil, false
}

// New creates a Failure from error Code.
Expand Down
20 changes: 14 additions & 6 deletions failure_test.go
Expand Up @@ -119,8 +119,14 @@ func TestFailure(t *testing.T) {
assert.Error(t, test.err)
}

assert.Equal(t, test.wantCode, failure.CodeOf(test.err))
assert.Equal(t, test.wantMessage, failure.MessageOf(test.err))
code, ok := failure.CodeOf(test.err)
assert.Equal(t, test.wantCode != nil, ok)
assert.Equal(t, test.wantCode, code)

msg, ok := failure.MessageOf(test.err)
assert.Equal(t, test.wantMessage != "", ok)
assert.Equal(t, test.wantMessage, msg)

assert.Equal(t, test.wantDebugs, failure.DebugsOf(test.err))

if test.wantError != "" {
Expand All @@ -129,14 +135,16 @@ func TestFailure(t *testing.T) {
assert.Nil(t, test.err)
}

cs := failure.CallStackOf(test.err)
cs, ok := failure.CallStackOf(test.err)
if test.wantStackLine != 0 {
assert.True(t, ok)
fs := cs.Frames()
require.NotEmpty(t, fs)
if !assert.Equal(t, test.wantStackLine, fs[0].Line()) {
t.Log(fs[0])
}
} else {
assert.False(t, ok)
assert.Nil(t, cs)
}
})
Expand All @@ -155,14 +163,14 @@ func TestFailure_Format(t *testing.T) {
exp := `failure.formatter{error:failure.withCallStack{.*`
assert.Regexp(t, exp, fmt.Sprintf("%#v", err))

exp = `\[failure_test.TestFailure_Format\] /.*/github.com/morikuni/failure/failure_test.go:149
\[failure_test.TestFailure_Format\] /.*/github.com/morikuni/failure/failure_test.go:148
exp = `\[failure_test.TestFailure_Format\] /.*/github.com/morikuni/failure/failure_test.go:157
\[failure_test.TestFailure_Format\] /.*/github.com/morikuni/failure/failure_test.go:156
zzz = true
message\("xxx"\)
code\(code_a\)
\*errors.errorString\("yyy"\)
\[CallStack\]
\[failure_test.TestFailure_Format\] /.*/github.com/morikuni/failure/failure_test.go:148
\[failure_test.TestFailure_Format\] /.*/github.com/morikuni/failure/failure_test.go:156
\[.*`
assert.Regexp(t, exp, fmt.Sprintf("%+v", err))
}
Expand Down
19 changes: 11 additions & 8 deletions wrapper.go
Expand Up @@ -51,9 +51,9 @@ func (w withMessage) GetMessage() string {
}

// MessageOf extracts the message from err.
func MessageOf(err error) string {
func MessageOf(err error) (string, bool) {
if err == nil {
return ""
return "", false
}

type messageGetter interface {
Expand All @@ -64,11 +64,11 @@ func MessageOf(err error) string {
for i.Next() {
err := i.Error()
if g, ok := err.(messageGetter); ok {
return g.GetMessage()
return g.GetMessage(), true
}
}

return ""
return "", false
}

// Debug is a key-value data appended to an error
Expand Down Expand Up @@ -147,9 +147,9 @@ func (w withCallStack) GetCallStack() CallStack {

// CallStackOf extracts call stack from the error.
// Returned call stack is for the most deepest place (appended first).
func CallStackOf(err error) CallStack {
func CallStackOf(err error) (CallStack, bool) {
if err == nil {
return nil
return nil, false
}

type callStackGetter interface {
Expand All @@ -171,7 +171,10 @@ func CallStackOf(err error) CallStack {
}
}

return last
if last == nil {
return nil, false
}
return last, true
}

// WithFormatter appends error formatter to an error.
Expand Down Expand Up @@ -249,7 +252,7 @@ func (f formatter) Format(s fmt.State, verb rune) {
}

fmt.Fprint(s, "[CallStack]\n")
if cs := CallStackOf(f); cs != nil {
if cs, ok := CallStackOf(f); ok {
for _, f := range cs.Frames() {
fmt.Fprintf(s, " %+v\n", f)
}
Expand Down