container/init: handle unwrapped errors
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 1m59s
Test / Hpkg (push) Successful in 3m32s
Test / Sandbox (race detector) (push) Successful in 3m54s
Test / Hakurei (race detector) (push) Successful in 5m16s
Test / Hakurei (push) Successful in 2m12s
Test / Flake checks (push) Successful in 1m29s
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 1m59s
Test / Hpkg (push) Successful in 3m32s
Test / Sandbox (race detector) (push) Successful in 3m54s
Test / Hakurei (race detector) (push) Successful in 5m16s
Test / Hakurei (push) Successful in 2m12s
Test / Flake checks (push) Successful in 1m29s
This is much cleaner from both the return statement and the error handling. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
parent
a462341a0a
commit
f24dd4ab8c
@ -6,6 +6,49 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// messageFromError returns a printable error message for a supported concrete type.
|
||||||
|
func messageFromError(err error) (string, bool) {
|
||||||
|
if m, ok := messagePrefixP[MountError, *MountError]("cannot ", err); ok {
|
||||||
|
return m, ok
|
||||||
|
}
|
||||||
|
if m, ok := messagePrefixP[os.PathError, *os.PathError]("cannot ", err); ok {
|
||||||
|
return m, ok
|
||||||
|
}
|
||||||
|
if m, ok := messagePrefixP[AbsoluteError, *AbsoluteError]("", err); ok {
|
||||||
|
return m, ok
|
||||||
|
}
|
||||||
|
if m, ok := messagePrefix[OpRepeatError]("", err); ok {
|
||||||
|
return m, ok
|
||||||
|
}
|
||||||
|
if m, ok := messagePrefix[OpStateError]("", err); ok {
|
||||||
|
return m, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
return zeroString, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// messagePrefix checks and prefixes the error message of a non-pointer error.
|
||||||
|
// While this is usable for pointer errors, such use should be avoided as nil check is omitted.
|
||||||
|
func messagePrefix[T error](prefix string, err error) (string, bool) {
|
||||||
|
var targetError T
|
||||||
|
if errors.As(err, &targetError) {
|
||||||
|
return prefix + targetError.Error(), true
|
||||||
|
}
|
||||||
|
return zeroString, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// messagePrefixP checks and prefixes the error message of a pointer error.
|
||||||
|
func messagePrefixP[V any, T interface {
|
||||||
|
*V
|
||||||
|
error
|
||||||
|
}](prefix string, err error) (string, bool) {
|
||||||
|
var targetError T
|
||||||
|
if errors.As(err, &targetError) && targetError != nil {
|
||||||
|
return prefix + targetError.Error(), true
|
||||||
|
}
|
||||||
|
return zeroString, false
|
||||||
|
}
|
||||||
|
|
||||||
type MountError struct {
|
type MountError struct {
|
||||||
Source, Target, Fstype string
|
Source, Target, Fstype string
|
||||||
|
|
||||||
|
@ -8,6 +8,52 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestMessageFromError(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
err error
|
||||||
|
want string
|
||||||
|
wantOk bool
|
||||||
|
}{
|
||||||
|
{"mount", &MountError{
|
||||||
|
Source: SourceTmpfsEphemeral,
|
||||||
|
Target: "/sysroot/tmp",
|
||||||
|
Fstype: FstypeTmpfs,
|
||||||
|
Flags: syscall.MS_NOSUID | syscall.MS_NODEV,
|
||||||
|
Data: zeroString,
|
||||||
|
Errno: syscall.EINVAL,
|
||||||
|
}, "cannot mount tmpfs on /sysroot/tmp: invalid argument", true},
|
||||||
|
|
||||||
|
{"path", &os.PathError{
|
||||||
|
Op: "mount",
|
||||||
|
Path: "/sysroot",
|
||||||
|
Err: errUnique,
|
||||||
|
}, "cannot mount /sysroot: unique error injected by the test suite", true},
|
||||||
|
|
||||||
|
{"absolute", &AbsoluteError{"etc/mtab"},
|
||||||
|
`path "etc/mtab" is not absolute`, true},
|
||||||
|
|
||||||
|
{"repeat", OpRepeatError("autoetc"),
|
||||||
|
"autoetc is not repeatable", true},
|
||||||
|
|
||||||
|
{"state", OpStateError("overlay"),
|
||||||
|
"impossible overlay state reached", true},
|
||||||
|
|
||||||
|
{"unsupported", errUnique, zeroString, false},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
got, ok := messageFromError(tc.err)
|
||||||
|
if got != tc.want {
|
||||||
|
t.Errorf("messageFromError: %q, want %q", got, tc.want)
|
||||||
|
}
|
||||||
|
if ok != tc.wantOk {
|
||||||
|
t.Errorf("messageFromError: ok = %v, want %v", ok, tc.wantOk)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMountError(t *testing.T) {
|
func TestMountError(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -184,10 +184,14 @@ func initEntrypoint(k syscallDispatcher, prepareLogger func(prefix string), setV
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := op.early(state, k); err != nil {
|
if err := op.early(state, k); err != nil {
|
||||||
k.printBaseErr(err,
|
if m, ok := messageFromError(err); ok {
|
||||||
fmt.Sprintf("cannot prepare op at index %d:", i))
|
k.fatal(m)
|
||||||
k.beforeExit()
|
} else {
|
||||||
k.exit(1)
|
k.printBaseErr(err,
|
||||||
|
fmt.Sprintf("cannot prepare op at index %d:", i))
|
||||||
|
k.beforeExit()
|
||||||
|
k.exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,10 +228,14 @@ func initEntrypoint(k syscallDispatcher, prepareLogger func(prefix string), setV
|
|||||||
// ops already checked during early setup
|
// ops already checked during early setup
|
||||||
k.verbosef("%s %s", op.prefix(), op)
|
k.verbosef("%s %s", op.prefix(), op)
|
||||||
if err := op.apply(state, k); err != nil {
|
if err := op.apply(state, k); err != nil {
|
||||||
k.printBaseErr(err,
|
if m, ok := messageFromError(err); ok {
|
||||||
fmt.Sprintf("cannot apply op at index %d:", i))
|
k.fatal(m)
|
||||||
k.beforeExit()
|
} else {
|
||||||
k.exit(1)
|
k.printBaseErr(err,
|
||||||
|
fmt.Sprintf("cannot apply op at index %d:", i))
|
||||||
|
k.beforeExit()
|
||||||
|
k.exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user