Skip to content

Commit

Permalink
specerror: Add NewRFCError and NewRFCErrorOrPanic
Browse files Browse the repository at this point in the history
So we don't have to dance around with casting to extract structured
information from NewError's returned error.

Signed-off-by: W. Trevor King <wking@tremily.us>
  • Loading branch information
wking committed Apr 18, 2018
1 parent 9185c46 commit dac7b67
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 19 deletions.
10 changes: 4 additions & 6 deletions cmd/runtimetest/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,13 @@ type complianceTester struct {
}

func (c *complianceTester) Ok(test bool, condition specerror.Code, version string, description string) (rfcError *rfc2119.Error, err error) {
err = specerror.NewError(condition, errors.New(description), version)
runtimeError, ok := err.(*specerror.Error)
if !ok {
return nil, fmt.Errorf("cannot convert %v to a runtime-spec error", err)
rfcError, err = specerror.NewRFCError(condition, errors.New(description), version)
if err != nil {
return nil, err
}
rfcError = &runtimeError.Err
if test {
c.harness.Pass(description)
} else if runtimeError.Err.Level < c.complianceLevel {
} else if rfcError.Level < c.complianceLevel {
c.harness.Skip(1, description)
} else {
c.harness.Fail(description)
Expand Down
37 changes: 30 additions & 7 deletions specerror/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,34 @@ func (err *Error) Error() string {
return err.Err.Error()
}

// NewRFCError creates an rfc2119.Error referencing a spec violation.
//
// A version string (for the version of the spec that was violated)
// must be set to get a working URL.
func NewRFCError(code Code, err error, version string) (*rfc2119.Error, error) {
template := ociErrors[code]
reference, err2 := template.Reference(version)
if err2 != nil {
return nil, err2
}
return &rfc2119.Error{
Level: template.Level,
Reference: reference,
Err: err,
}, nil
}

// NewRFCErrorOrPanic creates an rfc2119.Error referencing a spec
// violation and panics on failure. This is handy for situations
// where you can't be bothered to check NewRFCError for failure.
func NewRFCErrorOrPanic(code Code, err error, version string) (*rfc2119.Error) {
rfcError, err2 := NewRFCError(code, err, version)
if err2 != nil {
panic(err2.Error())
}
return rfcError
}

// NewError creates an Error referencing a spec violation. The error
// can be cast to an *Error for extracting structured information
// about the level of the violation and a reference to the violated
Expand All @@ -69,17 +97,12 @@ func (err *Error) Error() string {
// A version string (for the version of the spec that was violated)
// must be set to get a working URL.
func NewError(code Code, err error, version string) error {
template := ociErrors[code]
reference, err2 := template.Reference(version)
rfcError, err2 := NewRFCError(code, err, version)
if err2 != nil {
return err2
}
return &Error{
Err: rfc2119.Error{
Level: template.Level,
Reference: reference,
Err: err,
},
Err: *rfcError,
Code: code,
}
}
Expand Down
13 changes: 7 additions & 6 deletions validation/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/mndrix/tap-go"
rspecs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/specerror"
rfc2119 "github.com/opencontainers/runtime-tools/error"
"github.com/opencontainers/runtime-tools/validation/util"
uuid "github.com/satori/go.uuid"
)
Expand All @@ -26,11 +27,11 @@ func main() {
id string
action util.LifecycleAction
errExpected bool
err error
err *rfc2119.Error
}{
{"", util.LifecycleActionNone, false, specerror.NewError(specerror.QueryWithoutIDGenError, fmt.Errorf("state MUST generate an error if it is not provided the ID of a container"), rspecs.Version)},
{containerID, util.LifecycleActionNone, false, specerror.NewError(specerror.QueryNonExistGenError, fmt.Errorf("state MUST generate an error if a container that does not exist"), rspecs.Version)},
{containerID, util.LifecycleActionCreate | util.LifecycleActionDelete, true, specerror.NewError(specerror.QueryStateImplement, fmt.Errorf("state MUST return the state of a container as specified in the State section"), rspecs.Version)},
{"", util.LifecycleActionNone, false, specerror.NewRFCErrorOrPanic(specerror.QueryWithoutIDGenError, fmt.Errorf("state MUST generate an error if it is not provided the ID of a container"), rspecs.Version)},
{containerID, util.LifecycleActionNone, false, specerror.NewRFCErrorOrPanic(specerror.QueryNonExistGenError, fmt.Errorf("state MUST generate an error if a container that does not exist"), rspecs.Version)},
{containerID, util.LifecycleActionCreate | util.LifecycleActionDelete, true, specerror.NewRFCErrorOrPanic(specerror.QueryStateImplement, fmt.Errorf("state MUST return the state of a container as specified in the State section"), rspecs.Version)},
}

for _, c := range cases {
Expand All @@ -57,9 +58,9 @@ func main() {
continue
}

t.Ok((err == nil) == c.errExpected, c.err.(*specerror.Error).Err.Err.Error())
t.Ok((err == nil) == c.errExpected, c.err.Error())
diagnostic := map[string]string{
"reference": c.err.(*specerror.Error).Err.Reference,
"reference": c.err.Reference,
}
if err != nil {
diagnostic["error"] = err.Error()
Expand Down

0 comments on commit dac7b67

Please sign in to comment.