mirror of
https://github.com/MedUnes/go-kata.git
synced 2026-07-28 10:40:14 +07:00
create package
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
package myerror
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type MyError struct {
|
||||
Op string
|
||||
}
|
||||
|
||||
func (e *MyError) Error() string {
|
||||
if e == nil {
|
||||
return "<nil MyError>"
|
||||
}
|
||||
return fmt.Sprintf("operation failed: %s", e.Op)
|
||||
}
|
||||
|
||||
// BuggyDoThing returns a *MyError(nil) as error (typed nil pitfall)
|
||||
func BuggyDoThing(fail bool) error {
|
||||
if fail {
|
||||
return &MyError{Op: "fail"}
|
||||
}
|
||||
var e *MyError = nil
|
||||
return e // BAD: interface is non-nil!
|
||||
}
|
||||
|
||||
// FixedDoThing returns a true nil error when no error
|
||||
func FixedDoThing(fail bool) error {
|
||||
if fail {
|
||||
return &MyError{Op: "fail"}
|
||||
}
|
||||
return nil // GOOD: interface is nil
|
||||
}
|
||||
|
||||
// Wraps error for errors.As demonstration
|
||||
func WrapError(err error) error {
|
||||
return fmt.Errorf("wrapped: %w", err)
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package myerror
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDoThingMatrix(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fn func(bool) error
|
||||
fail bool
|
||||
wantNil bool
|
||||
wantType string
|
||||
}{
|
||||
{
|
||||
name: "BuggyDoThing returns typed nil (should NOT be nil)",
|
||||
fn: BuggyDoThing,
|
||||
fail: false,
|
||||
wantNil: false,
|
||||
wantType: "*myerror.MyError",
|
||||
},
|
||||
{
|
||||
name: "BuggyDoThing returns error (fail=true)",
|
||||
fn: BuggyDoThing,
|
||||
fail: true,
|
||||
wantNil: false,
|
||||
wantType: "*myerror.MyError",
|
||||
},
|
||||
{
|
||||
name: "FixedDoThing returns nil (should be nil)",
|
||||
fn: FixedDoThing,
|
||||
fail: false,
|
||||
wantNil: true,
|
||||
wantType: "<nil>",
|
||||
},
|
||||
{
|
||||
name: "FixedDoThing returns error (fail=true)",
|
||||
fn: FixedDoThing,
|
||||
fail: true,
|
||||
wantNil: false,
|
||||
wantType: "*myerror.MyError",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := tt.fn(tt.fail)
|
||||
gotNil := err == nil
|
||||
gotType := "<nil>"
|
||||
if err != nil {
|
||||
gotType = fmt.Sprintf("%T", err)
|
||||
}
|
||||
if gotNil != tt.wantNil {
|
||||
t.Errorf("expected nil: %v, got: %v (type: %s, value: %#v)", tt.wantNil, gotNil, gotType, err)
|
||||
}
|
||||
if gotType != tt.wantType {
|
||||
t.Errorf("expected type: %s, got: %s", tt.wantType, gotType)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorsAsExtractionMatrix(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
wrap bool
|
||||
expectOp string
|
||||
}{
|
||||
{
|
||||
name: "Direct MyError",
|
||||
wrap: false,
|
||||
expectOp: "extract",
|
||||
},
|
||||
{
|
||||
name: "Wrapped MyError",
|
||||
wrap: true,
|
||||
expectOp: "extract",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
orig := &MyError{Op: "extract"}
|
||||
var err error = orig
|
||||
if tt.wrap {
|
||||
err = WrapError(err)
|
||||
}
|
||||
var me *MyError
|
||||
if !errors.As(err, &me) {
|
||||
t.Fatalf("errors.As failed to extract *MyError")
|
||||
}
|
||||
if me == nil || me.Op != tt.expectOp {
|
||||
t.Fatalf("extracted wrong value: %#v", me)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user