diff --git a/error_test.go b/error_test.go index c42a229..6d50b6f 100644 --- a/error_test.go +++ b/error_test.go @@ -1,6 +1,13 @@ package wasi_test import ( + "context" + "fmt" + "io" + "io/fs" + "net" + "os" + "syscall" "testing" "github.com/stealthrocket/wasi-go" @@ -17,3 +24,29 @@ func TestErrno(t *testing.T) { }) } } + +func TestMakeErrno(t *testing.T) { + tests := []struct { + error error + errno wasi.Errno + }{ + {nil, wasi.ESUCCESS}, + {syscall.EAGAIN, wasi.EAGAIN}, + {context.Canceled, wasi.ECANCELED}, + {context.DeadlineExceeded, wasi.ETIMEDOUT}, + {io.ErrUnexpectedEOF, wasi.EIO}, + {fs.ErrClosed, wasi.EIO}, + {net.ErrClosed, wasi.EIO}, + {syscall.EPERM, wasi.EPERM}, + {wasi.EAGAIN, wasi.EAGAIN}, + {os.ErrDeadlineExceeded, wasi.ETIMEDOUT}, + } + + for _, test := range tests { + t.Run(fmt.Sprint(test.error), func(t *testing.T) { + if errno := wasi.MakeErrno(test.error); errno != test.errno { + t.Errorf("error mismatch: want=%d got=%d (%s)", test.errno, errno, errno) + } + }) + } +} diff --git a/error_unix.go b/error_unix.go index c12e9e2..9d9b178 100644 --- a/error_unix.go +++ b/error_unix.go @@ -4,6 +4,9 @@ import ( "context" "errors" "fmt" + "io" + "io/fs" + "net" "syscall" ) @@ -18,9 +21,17 @@ func makeErrno(err error) Errno { } func makeErrnoSlow(err error) Errno { - if err == context.Canceled { + switch { + case errors.Is(err, context.Canceled): return ECANCELED + case errors.Is(err, context.DeadlineExceeded): + return ETIMEDOUT + case errors.Is(err, io.ErrUnexpectedEOF), + errors.Is(err, fs.ErrClosed), + errors.Is(err, net.ErrClosed): + return EIO } + var sysErrno syscall.Errno if errors.As(err, &sysErrno) { if sysErrno == 0 { @@ -28,12 +39,19 @@ func makeErrnoSlow(err error) Errno { } return syscallErrnoToWASI(sysErrno) } + + var wasiErrno Errno + if errors.As(err, &wasiErrno) { + return wasiErrno + } + var timeout interface{ Timeout() bool } if errors.As(err, &timeout) { if timeout.Timeout() { return ETIMEDOUT } } + panic(fmt.Errorf("unexpected error: %v", err)) }