Skip to content
Permalink
Browse files

Tests, changelog, license, mod

  • Loading branch information...
ztrue committed Feb 8, 2019
1 parent aa9378b commit 89b8b13125d146a28c9a8595809c2f7d4ffddb43
Showing with 796 additions and 20 deletions.
  1. +1 −0 .gitignore
  2. +12 −0 .travis.yml
  3. +23 −0 CHANGELOG.md
  4. +21 −0 LICENSE
  5. +22 −3 Makefile
  6. +4 −2 README.md
  7. +11 −6 error.go
  8. +18 −0 error_helper_test.go
  9. +208 −0 error_test.go
  10. +3 −0 go.mod
  11. +2 −0 go.sum
  12. +16 −9 print.go
  13. +455 −0 print_test.go
@@ -0,0 +1 @@
/coverage.out
@@ -0,0 +1,12 @@
language: go

before_install:
- go get github.com/mattn/goveralls

go:
- "1.11.x"
- "1.10.x"

script:
- go test -cover -v -covermode=count -coverprofile=coverage.out
- $GOPATH/bin/goveralls -coverprofile=coverage.out -service=travis-ci
@@ -0,0 +1,23 @@
# Changelog

## [0.1.1] - 2019-02-09

### Added

- Changelog.
- `go.mod` file.
- License.
- Tests with 100% coverage.
- Travis CI.

### Changed

- `Error.Err` and `Error.Frames` properties are now exported.
- `Error.Error()` called on `nil` now returns empty string instead of panics.
- All print and sprint functions called with `nil` error now returns or prints empty string instead of panics.

## [0.1.0] - 2019-02-06

### Added

- Initial version.
21 LICENSE
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2019 ztrue <gztrue@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -1,8 +1,27 @@
.PHONY: fmt default: test
fmt:
go fmt . && go fmt ./examples .PHONY: install
install:
go get github.com/logrusorgru/aurora

.PHONY: lint
lint:
go fmt . && \
go fmt ./examples && \
go vet && \
golint $$(go list ./...)


.PHONY: doc .PHONY: doc
doc: doc:
@echo GoDoc link: http://localhost:6060/pkg/github.com/ztrue/tracerr @echo GoDoc link: http://localhost:6060/pkg/github.com/ztrue/tracerr
godoc -http=:6060 godoc -http=:6060

.PHONY: test
test:
go test -cover -v

.PHONY: coverage
coverage:
go test -coverprofile=coverage.out && \
go tool cover -func=coverage.out && \
go tool cover -html=coverage.out
@@ -1,13 +1,15 @@
# Golang Errors with Stack Trace and Source Fragments # Golang Errors with Stack Trace and Source Fragments


[![GoDoc](https://godoc.org/github.com/ztrue/tracerr?status.svg)](https://godoc.org/github.com/ztrue/tracerr) [![GoDoc](https://godoc.org/github.com/ztrue/tracerr?status.svg)](https://godoc.org/github.com/ztrue/tracerr)
[![GoReport](https://goreportcard.com/badge/github.com/ztrue/tracerr)](https://goreportcard.com/report/github.com/ztrue/tracerr) [![Report](https://goreportcard.com/badge/github.com/ztrue/tracerr)](https://goreportcard.com/report/github.com/ztrue/tracerr)
[![Coverage Status](https://coveralls.io/repos/github/ztrue/tracerr/badge.svg?branch=master)](https://coveralls.io/github/ztrue/tracerr?branch=master)
[![Build Status](https://travis-ci.com/ztrue/tracerr.svg?branch=master)](https://travis-ci.com/ztrue/tracerr)


Tired of uninformative error output? Probably this will be more convenient: Tired of uninformative error output? Probably this will be more convenient:


![Output](output.png) ![Output](output.png)


## Sample ## Example


```go ```go
package main package main
@@ -11,8 +11,10 @@ import (


// Error is an error with stack trace. // Error is an error with stack trace.
type Error struct { type Error struct {
frames []Frame // Error contains original error.
err error Err error
// Frames contains stack trace of an error.
Frames []Frame
} }


// Errorf creates new error with stacktrace and formatted message. // Errorf creates new error with stacktrace and formatted message.
@@ -40,15 +42,18 @@ func Wrap(err error) *Error {


// Error returns error message. // Error returns error message.
func (e *Error) Error() string { func (e *Error) Error() string {
return e.err.Error() if e == nil {
return ""
}
return e.Err.Error()
} }


// StackTrace returns stack trace of an error. // StackTrace returns stack trace of an error.
func (e *Error) StackTrace() []Frame { func (e *Error) StackTrace() []Frame {
if e == nil { if e == nil {
return nil return nil
} }
return e.frames return e.Frames
} }


// Frame is a single step in stack trace. // Frame is a single step in stack trace.
@@ -93,7 +98,7 @@ func trace(err error, skip int) *Error {
skip++ skip++
} }
return &Error{ return &Error{
frames: frames, Err: err,
err: err, Frames: frames,
} }
} }
@@ -0,0 +1,18 @@
// This file is added for purpose of having an example of different path in tests.
package tracerr_test

import (
"github.com/ztrue/tracerr"
)

func addFrameA(message string) *tracerr.Error {
return addFrameB(message)
}

func addFrameB(message string) *tracerr.Error {
return addFrameC(message)
}

func addFrameC(message string) *tracerr.Error {
return tracerr.New(message)
}
@@ -0,0 +1,208 @@
package tracerr_test

import (
"errors"
"fmt"
"strings"
"testing"

"github.com/ztrue/tracerr"
)

type ErrorTestCase struct {
Error *tracerr.Error
ExpectedMessage string
ExpectedStackTrace []tracerr.Frame
}

func TestError(t *testing.T) {
cases := []ErrorTestCase{
{
Error: nil,
ExpectedMessage: "",
ExpectedStackTrace: nil,
},
{
Error: tracerr.Wrap(nil),
ExpectedMessage: "",
ExpectedStackTrace: nil,
},
{
Error: tracerr.New("error message text"),
ExpectedMessage: "error message text",
ExpectedStackTrace: []tracerr.Frame{
{
Func: "github.com/ztrue/tracerr_test.TestError",
Line: 31,
Path: "/src/github.com/ztrue/tracerr/error_test.go",
},
},
},
{
Error: tracerr.Errorf("invalid argument %d: %#v", 5, "foo"),
ExpectedMessage: "invalid argument 5: \"foo\"",
ExpectedStackTrace: []tracerr.Frame{
{
Func: "github.com/ztrue/tracerr_test.TestError",
Line: 42,
Path: "/src/github.com/ztrue/tracerr/error_test.go",
},
},
},
{
Error: tracerr.Wrap(errors.New("wrapped error")),
ExpectedMessage: "wrapped error",
ExpectedStackTrace: []tracerr.Frame{
{
Func: "github.com/ztrue/tracerr_test.TestError",
Line: 53,
Path: "/src/github.com/ztrue/tracerr/error_test.go",
},
},
},
{
Error: addFrameA("error with stack trace"),
ExpectedMessage: "error with stack trace",
ExpectedStackTrace: []tracerr.Frame{
{
Func: "github.com/ztrue/tracerr_test.addFrameC",
Line: 17,
Path: "/src/github.com/ztrue/tracerr/error_helper_test.go",
},
{
Func: "github.com/ztrue/tracerr_test.addFrameB",
Line: 13,
Path: "/src/github.com/ztrue/tracerr/error_helper_test.go",
},
{
Func: "github.com/ztrue/tracerr_test.addFrameA",
Line: 9,
Path: "/src/github.com/ztrue/tracerr/error_helper_test.go",
},
{
Func: "github.com/ztrue/tracerr_test.TestError",
Line: 64,
Path: "/src/github.com/ztrue/tracerr/error_test.go",
},
},
},
{
Error: tracerr.Wrap(addFrameA("error wrapped twice")),
ExpectedMessage: "error wrapped twice",
ExpectedStackTrace: []tracerr.Frame{
{
Func: "github.com/ztrue/tracerr_test.addFrameC",
Line: 17,
Path: "/src/github.com/ztrue/tracerr/error_helper_test.go",
},
{
Func: "github.com/ztrue/tracerr_test.addFrameB",
Line: 13,
Path: "/src/github.com/ztrue/tracerr/error_helper_test.go",
},
{
Func: "github.com/ztrue/tracerr_test.addFrameA",
Line: 9,
Path: "/src/github.com/ztrue/tracerr/error_helper_test.go",
},
{
Func: "github.com/ztrue/tracerr_test.TestError",
Line: 90,
Path: "/src/github.com/ztrue/tracerr/error_test.go",
},
},
},
}

for i, c := range cases {
if c.Error.Error() != c.ExpectedMessage {
t.Errorf(
"cases[%#v].Error.Error() = %#v; want %#v",
i, c.Error.Error(), c.ExpectedMessage,
)
}

if c.ExpectedStackTrace == nil {
if c.Error.StackTrace() != nil {
t.Errorf(
"cases[%#v].Error.StackTrace() = %#v; want %#v",
i, c.Error.StackTrace(), nil,
)
}
if tracerr.StackTrace(c.Error) != nil {
t.Errorf(
"tracerr.StackTrace(cases[%#v].Error) = %#v; want %#v",
i, tracerr.StackTrace(c.Error), nil,
)
}
continue
}

frames1 := c.Error.StackTrace()
frames2 := tracerr.StackTrace(c.Error)
for k, frames := range [][]tracerr.Frame{frames1, frames2} {
// Different failing message, depend on stack trace method.
var pattern string
if k == 0 {
pattern = "cases[%#v].Error.StackTrace()"
} else {
pattern = "tracerr.StackTrace(cases[%#v].Error)"
}
prefix := fmt.Sprintf(pattern, i)
// There must be at least two frames of test runner.
expectedMinLen := len(c.ExpectedStackTrace) + 2
if len(frames) < expectedMinLen {
t.Errorf(
"len(%s) = %#v; want >= %#v",
prefix, len(frames), expectedMinLen,
)
}
for j, expectedFrame := range c.ExpectedStackTrace {
if frames[j].Func != expectedFrame.Func {
t.Errorf(
"%s[%#v].Func = %#v; want %#v",
prefix, j, frames[j].Func, expectedFrame.Func,
)
}
if frames[j].Line != expectedFrame.Line {
t.Errorf(
"%s[%#v].Line = %#v; want %#v",
prefix, j, frames[j].Line, expectedFrame.Line,
)
}
if !strings.HasSuffix(frames[j].Path, expectedFrame.Path) {
t.Errorf(
"%s[%#v].Path = %#v; want to has suffix %#v",
prefix, j, frames[j].Path, expectedFrame.Path,
)
}
}
}

}
}

func TestFrameString(t *testing.T) {
frame := tracerr.Frame{
Func: "main.read",
Line: 1337,
Path: "/src/github.com/john/doe/foobar.go",
}
expected := "/src/github.com/john/doe/foobar.go:1337 main.read()"
if frame.String() != expected {
t.Errorf(
"frame.String() = %#v; want %#v",
frame.String(), expected,
)
}
}

func TestStackTraceNotInstance(t *testing.T) {
err := errors.New("regular error")
if tracerr.StackTrace(err) != nil {
t.Errorf(
"tracerr.StackTrace(%#v) = %#v; want %#v",
err, tracerr.StackTrace(err), nil,
)
}
}
3 go.mod
@@ -0,0 +1,3 @@
module github.com/ztrue/tracerr

require github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e
2 go.sum
@@ -0,0 +1,2 @@
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k=
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
Oops, something went wrong.

0 comments on commit 89b8b13

Please sign in to comment.
You can’t perform that action at this time.