Probe revamped to provide for a new WrappedError struct to wrap probes as error interface

This convenience was necessary to be used for golang library functions like io.Copy and io.Pipe
where we shouldn't be writing proxies and alternatives returning *probe.Error

This change also brings more changes across code base for clear separation regarding where an error
interface should be passed encapsulating *probe.Error and where it should be used as is.
This commit is contained in:
Harshavardhana
2015-08-07 23:47:22 -07:00
parent 28d9565400
commit 45b59b8456
34 changed files with 392 additions and 363 deletions

View File

@@ -66,11 +66,11 @@ type Error struct {
tracePoints []tracePoint
}
// New function instantiates an error probe for tracing. Original errors.error (golang's error
// NewError function instantiates an error probe for tracing. Original errors.error (golang's error
// interface) is injected in only once during this New call. Rest of the time, you
// trace the return path with Probe.Trace and finally handle reporting or quitting
// at the top level.
func New(e error) *Error {
func NewError(e error) *Error {
if e == nil {
return nil
}
@@ -124,17 +124,9 @@ func (e *Error) Untrace() {
e.tracePoints = e.tracePoints[:l-1]
}
// Error returns error string.
func (e *Error) Error() string {
if e == nil {
return "<nil>"
}
return e.String()
}
// String returns error message.
func (e *Error) String() string {
if e == nil {
if e == nil || e.e == nil {
return "<nil>"
}
e.lock.RLock()
@@ -164,7 +156,7 @@ func (e *Error) String() string {
// JSON returns JSON formated error trace.
func (e *Error) JSON() string {
if e == nil {
if e == nil || e.e == nil {
return "<nil>"
}
@@ -187,8 +179,38 @@ func (e *Error) JSON() string {
return string(jBytes)
}
// ToError returns original emnedded error.
// ToError returns original embedded error.
func (e *Error) ToError() error {
// No need to lock. "e.e" is set once during New and never changed.
return e.e
}
// WrappedError implements container for *probe.Error
type WrappedError struct {
err *Error
}
// NewWrappedError function wraps a *probe.Error into a 'error' compatible duck type
func NewWrappedError(err *Error) error {
return &WrappedError{err: err}
}
// Error interface method
func (w *WrappedError) Error() string {
return w.err.String()
}
// ToError get the *probe.Error embedded internally
func (w *WrappedError) ToError() *Error {
return w.err
}
// ToWrappedError try to convert generic 'error' into typed *WrappedError, returns true if yes, false otherwise
func ToWrappedError(err error) (*WrappedError, bool) {
switch e := err.(type) {
case *WrappedError:
return e, true
default:
return nil, false
}
}

View File

@@ -13,33 +13,41 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package probe
package probe_test
import (
"os"
"testing"
"github.com/minio/minio/pkg/probe"
. "gopkg.in/check.v1"
)
func testDummy() *Error {
_, e := os.Stat("this-file-cannot-exit-234234232423423")
es := New(e)
es.Trace("this is hell", "asdf")
func Test(t *testing.T) { TestingT(t) }
type MySuite struct{}
var _ = Suite(&MySuite{})
func testDummy() *probe.Error {
_, e := os.Stat("this-file-cannot-exit")
es := probe.NewError(e)
es.Trace("Important info 1", "Import into 2")
return es
}
func TestProbe(t *testing.T) {
func (s *MySuite) TestProbe(c *C) {
es := testDummy()
if es == nil {
t.Fail()
}
c.Assert(es, Not(Equals), nil)
newES := es.Trace()
if newES == nil {
t.Fail()
}
/*
fmt.Println(es)
fmt.Println(es.JSON())
fmt.Println(es.ToError())
*/
c.Assert(newES, Not(Equals), nil)
}
func (s *MySuite) TestWrappedError(c *C) {
_, e := os.Stat("this-file-cannot-exit")
es := probe.NewError(e) // *probe.Error
e = probe.NewWrappedError(es) // *probe.WrappedError
_, ok := probe.ToWrappedError(e)
c.Assert(ok, Equals, true)
}